This page describes the control plane: the layer that resolves every credential and authorization decision before an agent does any work. These controls are not opt-in hardening; the control plane applies them to every agent it launches. Workbench runs on the control plane and inherits them. Intercode does not run on the control plane, so the controls described here do not govern it.
Two primitives
Everything reduces to two things:Credentials
The secrets an agent uses to authenticate with an outside service — an API key, an OAuth token, a certificate. Owned and stored by your organization, never discovered by the agent.
Grants
The atomic unit of authorization. Every decision the control plane makes about what an agent may do is resolved by evaluating grants. A capability with no matching grant is denied.
Credentials
A credential is a runtime secret an agent uses to authenticate with a provider — GitHub, OpenAI, Slack, Google Drive, an internal deployment service, an SSH bastion. Every credential belongs to a provider; there are no provider-less credentials. The provider definition is what tells the control plane how to handle the credential: its refresh behavior, its authentication method, its scope model. The credential’s type — API key, OAuth token, certificate — is a property of the credential, not something the agent chooses. From the agent’s side, it needs “access to service X,” and the control plane figures out the authentication mechanism. Agents do not select or negotiate credential types.Resolved at launch, never at runtime
This is the principle that makes credentials auditable:Agents never discover or look up credentials at runtime. When an agent launches, the control plane resolves the credentials it needs and hands them to the agent’s harness as part of launch. The harness holds them in memory for the agent’s lifetime and mediates every use — proxying requests with authentication attached, or injecting the credential into the runtime.
Credential secrets are encrypted at rest. Every write path seals the secret before it reaches the database, and each ciphertext is bound to its own row and column, so a value lifted from one row will not decrypt in another. Today that binding is AES-256-GCM under a single operator-provided key. It is not KMS-managed or envelope-encrypted, and we do not claim it is; the encryption seam is pluggable so a KMS implementation replaces it without touching a call site. The architectural guarantee is unchanged: credentials are resolved and scoped at launch, and agents never look them up themselves.
Two independent axes
Credentials vary along two axes that are easy to conflate. Keep them separate.Ownership — organizational vs. personal
Ownership — organizational vs. personal
A credential can optionally be owned by a specific principal in the tenant.
- Organizational — no principal owner. Shared across the tenant and managed by administrators. This is the company’s OpenAI key, its deploy token.
- Personal — owned by a specific user or agent, typically created through an OAuth flow where that user authorized Corbits to act on their behalf with a third-party service.
Source — where a requirement pulls its credential from
Source — where a requirement pulls its credential from
An agent definition declares which credential a requirement should resolve to by source:
tenant— the tenant’s organizational credential.creator— the agent author’s personal credential.invoker— the user launching the agent supplies their own.
tenant-sourced credential is shared; an invoker-sourced one is not. Do not read “shared” as “invoker.”Using a credential requires a grant
Referencing a credential in a definition does not authorize using it. When the control plane resolves the credential an agent uses to reach its model provider, it checks that the agent’s creator holds a grant to use that specific credential: resourcecredential:{id}, action use, collected across the tenant ancestor chain so an inherited credential still resolves. This check is against the creator’s own authority, not the grants materialized on the running agent’s principal that the rest of this page describes. Anything short of an explicit allow withholds the secret: an ask, a deny, or no matching grant all fail closed. Launch and credential rotation share this one check, so a secret cannot reach an agent by either path without it.
This closes a real gap: authoring a definition no longer confers use of the credentials it names, and an invoker cannot route around the check by pinning a provider whose credential the creator is not authorized to use: that model is simply unavailable, and the secret is never spent. Owners receive the use grant when they create a credential, and existing personal credentials were backfilled, so the gate does not lock anyone out of their own.
Gating credential use on the creator’s grant is a deliberate interim tightening, stricter than the source model (tenant, creator, invoker) strictly requires. A tenant-owned credential would normally be authorized by tenant or role policy; until that model subsumes this path, the creator’s
use grant is the authoritative check.Grants
Grants are the atomic unit of authorization. Every authorization decision the control plane makes is resolved by evaluating grants. A grant carries three fields:
A grant attaches either to a role — a named bundle of grants scoped to a tenant, assigned to users and agents — or directly to a principal. System roles (owner, admin, member) are created with every tenant; admins can define custom roles on top.
How a decision is made
For any principal attempting any operation, the engine:1
Collect
Gather every grant that applies — direct grants on the principal plus grants from all of its roles.
2
Filter
Keep only grants whose
resource and action patterns match the operation.3
Order by specificity
More specific patterns beat less specific ones — a grant on
credential:crd_gdrive outranks one on *.4
Most specific grant decides — ties break toward denial
The most specific matching grant sets the effect. When two matching grants are equally specific, the most restrictive effect wins: deny beats ask beats allow, so ambiguity always resolves toward less access.
5
No match → deny
If nothing matches, the evaluator returns no decision and the control plane fails closed, denying the operation by default.
ask effect blocks execution and records a pending approval. The control plane pushes no prompt and assigns no one: resolving an approval is itself a grant-gated action, evaluated like any other. An approver is any principal whose grant allows resolve on the approval. That grant’s breadth sets what they can reach: a tenant-wide approval:* grant lists the whole pending queue, while a grant covering just one agent’s approvals cannot list and instead fetches each one by its id. Any such approver can approve the action once or reject it. A control-plane approval is one-time: it authorizes that action, not future ones. Any conditions on the grant that produced the ask (time windows, approval thresholds, rate limits) are evaluated as the decision is made; a grant whose conditions are unmet is skipped. How the blocked call is parked durably, resolved exactly once, and resumed without re-running the agent is the durable approval substrate, covered in Approvals.
Durable “approve always” is not one of those outcomes today: the control plane’s approval path is approve-once-or-reject and does not yet support scope: "always" (it returns unsupported_scope). The durable capability lives one layer up, in the app. Workbench records a member’s decision to auto-approve a tool as a durable row of its own; on the next grant reconcile that tool drops out of the ask set, so the control plane provisions its grant as allow rather than ask and it stops suspending. The approval never mints authority: the durable allow is an ordinary provisioned grant driven by Workbench’s recorded decision, and revoking that decision reverts the tool to ask. Notification is app-layer too: on top of that pull queue, Workbench adds the approver-facing prompts the control plane does not (a bell, an inbox).
Fail-closed is the property compliance cares about most. There is no implicit allow, no ambient authority, no capability that works “because nobody blocked it.” Silence is denial.
Where authority comes from: requirement sources
An agent definition does not ship live grants. It ships requirements — a manifest of the capabilities it needs. At launch, the control plane resolves each requirement against real authority and materializes grants on the agent’s own principal. A definition declares credential requirements and grant requirements separately, and the two do not draw from the same sources: a credential requirement can nametenant, creator, or invoker, while a grant requirement is limited to creator and invoker. A grant requirement that names any other source is refused at launch.
tenant
Credential requirements only. The control plane resolves a credential the organization owns, one stored with no principal of its own, walking up the tenant hierarchy until it finds a match. This source resolves no grants, and a grant requirement cannot name it.
creator
The definition author delegates authority they themselves currently hold. This is the setuid model: the author’s authority travels with the definition. A creator cannot delegate what they do not have — the control plane checks at every launch.
invoker
The person launching the agent must supply it, and they cannot pass along authority that was itself delegated to them by an invoker. Materialized as a grant that expires 24 hours after launch, a fixed lifetime that does not track how long the agent actually runs.
The thesis: inert without both
A tool is a capability that does nothing on its own.- A tool is inert without a grant.
tool:bashneeds one thing to run: a grant that allowsinvokeontool:bash. No credential is involved. - A tool that reaches an external provider is additionally inert without a resolved, grant-authorized credential. The credential must resolve at launch, and a grant on
credential:...with actionusemust authorize this principal to use it.
Tenant hierarchy and inheritance
Authority is organized by tenant.- A principal is an identity within a tenant — the join between an entity and that tenant. An entity is a person or an agent. A person’s principal is their user account in that tenant; an agent gets a principal per run, rather than one standing for the definition it was deployed from. A principal by itself grants nothing; it only establishes that the entity exists in the tenant.
- A tenant is the isolation boundary. It has a nullable
parent_id, so tenants form a hierarchy of parents and sub-tenants (child tenants).
- Credentials inherit (walk-up)
- Grants do not inherit
When the control plane looks for a credential, it checks the current tenant, then walks up the parent chain until it finds a match or reaches the root. Store an organizational credential at the parent tenant and every child tenant can resolve it automatically — define your integrations once for the whole org.A child tenant can shadow a parent’s credential by creating one with the same name; the child’s takes precedence within its scope. Names are unique within a tenant, which is what makes name-based shadowing work.
A worked example
An organization stores one Google Drive credential scoped to its financial records at the org (parent) tenant — call its resourcecredential:crd_gdrive_financials. Because credentials walk up the hierarchy, every department inherits it: marketing, engineering, accounting all resolve the same credential.
But only principals in the accounting department hold the grant that authorizes using it:
1
The credential is reachable
Walk-up resolution can find
crd_gdrive_financials at the parent tenant — every department inherits it, so it is available for the marketing agent to resolve.2
A grant is required to use it
Using that credential requires a grant:
credential:crd_gdrive_financials with action use. The engine looks for one on the marketing principal and finds none — that grant lives only on accounting principals.3
Denied, fail-closed
No matching grant means deny. Inheritance put the credential within reach; without the grant, the marketing agent is refused — whether that refusal lands at launch or at first use, the answer is no.
Audit and provenance
Authorization decides what an agent may do. Provenance records what it did and makes that record verifiable rather than something you take on trust. For an agent running on the control plane, the runtime commits conversation context and audit records on its behalf. All of it lands in that agent’s own git repository, and every commit is signed with the key registered to that agent using the standard SSH signature format. The result is a tamper-evident history: any commit altered after the fact no longer verifies, so a recorded action cannot be rewritten without breaking its signature.Verification uses standard git.
git verify-commit checks a commit against the published key that signed it, which is one of the keys the control plane holds. You can confirm authenticity yourself, outside the platform. The control plane enforces the matching check on its side: it rejects any state commit not signed by the agent’s registered key, so unsigned or mis-signed history never lands in the first place.Transport and supply chain
Two controls sit underneath the credential and grant model. Neither decides what an agent may do; both bound who can present themselves as part of the system and what code can enter it. The sidecar connection is authenticated. Agent execution happens in a sidecar that connects back to the control plane over a WebSocket. That connection is authenticated on the handshake against the sidecar’s own identity token, which is a distinct secret from any credential the sidecar is later given to work with. The control plane stores only a digest of that identity token, never the token itself, so reading the database yields nothing that can be replayed to impersonate a sidecar. A handshake that does not resolve to a known sidecar is rejected rather than trusted on the strength of what the connecting party claims about itself. Tool packages are integrity-checked. Third-party tool packages are distributed as npm tarballs and land in a content-addressable cache keyed by a sha512 digest, so a given digest always resolves to the same bytes and a tampered or substituted tarball does not match the integrity value recorded for it. This is a property of the agent runtime’s packaging layer, documented across the platform overview, rather than a control-plane authorization decision: it governs what code can be loaded, while grants continue to govern what that code is allowed to do once loaded.How this shows up
Platform overview
Where credentials and grants sit in the control plane, harness, and agent lifecycle.
Intercode
The guardrails discipline in a real coding agent — tiered permissions and hard-deny secret guards.
Workbench
A go-to-market workspace running on control-plane-governed credentials and grants.