owner,
admin, and member; creator and collaborator are app-level access categories.
People with app-level build access can keep iterating in a draft, while the
published app keeps serving the last reviewed snapshot to its teams.
The goal is simple: builders can move quickly, but the runtime that team members
use is the version an admin or owner intentionally allowed to use real data and
integrations.
Source control is a separate app source storage layer. Connecting a provider
such as GitHub, GitLab, or Bitbucket does not publish or upload apps by itself.
Local CLI/desktop installs use explicit app-level Publish to source control.
On-prem or managed deployments can enable a workspace-level Store app source in
source control policy so successful builds store app source in the configured
provider and create auto-versioned second-app-v<N> tags. This is separate
from Available Apps discovery and from the normal review/publish flow. See
Source Control.
Roles and app access
Local
none auth is optimized for single-user development. External/on-prem
deployments use the same code paths, but members create review requests and
admins/owners approve before publishing.
Draft and published snapshots
Apps have two source snapshots:
Editing a published app creates or updates the draft only. The published app
continues to use the published snapshot until a new publish or review approval
promotes the draft. The
apps document stores snapshot IDs, hashes, file
counts, and byte sizes so app lists, navigation, review inboxes, and access
checks do not load source files. Older apps with embedded sourceFiles or
publishedSourceFiles are still readable as a compatibility fallback.
If an app is already in review and someone keeps editing it, the pending review
is marked superseded and the app returns to draft. The UI tells the builder
they are now editing an unpublished version and must request review again.
Review flow
- Builder finishes a draft.
- App creator/collaborator selects target teams and requests review.
- Admin/owner reviews the app, integration requirements, and agent config.
- Approval promotes the current draft source snapshot into the published source snapshot.
- Team viewers use the promoted published snapshot.
agents.json, calling present_agents, or approving the Agents card
does not create a review request and does not publish the app. Review starts
only through the publish dialog.
Governed agents.json
agents.json is editable draft code, but it is not trusted runtime
configuration until the platform records an approval for the versioned
canonical JSON hash.
The flow is:
vN:<sha256> so future agents.json schema changes can keep previous approval
semantics stable. In the current v1 schema, harmless empty optional arrays
such as top-level appTools: [], agent-level tools: [], and agent-level
dataCollections: [] are normalized away before hashing. A schema change that
adds or changes defaulted fields should add a new hash version rather than
changing the old version’s normalization rules.
Any later agents.json change clears the draft approval. It does not matter
whether the change came from a UI toggle, a file edit, or a worker shell command:
the source persistence path compares the versioned canonical hash and marks the
approval stale if it changed.
Draft app-agent runs can start from the draft file so builders can test the
in-progress app. Custom HTTP tools and agent data tools still require the
current draft hash to match the stored approval before they can touch live
integrations or app data. Publishing or review approval promotes the approved
payload with the published snapshot, so published runtime continues to use the
reviewed configuration.
Integration and domain approval
Integrations are app-scoped grants under workspace governance. Admins and owners configure static secrets or workspace OAuth provider clients and mark the currently requested permission groups, scopes, and secret names as configured. The agent never receives static secret values, OAuth client secrets, refresh tokens, or access tokens. Custom tools are tied to an integration domain inagents.json, for example
slack.com or hubapi.com. At runtime, /api/internal/tool-execute:
- Loads the current app’s integration grant by
(workspaceId, appId, domain, keySlug). - Verifies the tool exists in the approved
agents.jsonpayload for that agent. - For static tools, reads named secrets from Vault or local development storage.
- For OAuth tools, loads the server-created app-agent run by
(workspaceId, appId, runId), resolves the triggering user, checks that user’s connected account and scopes, refreshes the access token on demand, and injects the bearer token server-side. - Substitutes only named static secret placeholders such as
{{secrets.SLACK_BOT_TOKEN}}. - Validates that the final URL hostname matches the configured domain or one of its subdomains.
- Rejects private/internal IPs, non-HTTPS production URLs, oversized responses, and broad static calls when input was provided.
agents.json to request a new domain, endpoint, auth mode, OAuth scope, token
URL, secret, permission, or data collection, that draft must be approved again
before runtime can use it.
Draft data isolation
Draft and published app data are also separated. Published apps read and write under the app’s normal data scope. Draft previews and draft app-agent runs use an internal draft data scope for the same app. This lets builders test changes without mutating the live data used by the published app. All data queries still includeworkspaceId and the scoped app ID. Agent data
tools also verify that the requested collection appears in the approved
agents.json payload for the calling agent.