Skip to main content

COG-13: Agent Capabilities

Status:      Draft (Work in Progress)
Version: 0.1
Created: 2026-04-12
Authors: Mike Anderson
Work in Progress

This specification is under active development. Structure and details may change significantly based on implementation experience and community feedback.

This standard specifies the capability model for agent authorisation on the Covia Grid — how fine-grained access to operations and resources is granted to agents, attenuated through delegation, disclosed in agent context, and enforced at runtime.

This COG supersedes the "Capability enforcement" future direction in COG-11: Agent Lifecycle by providing the complete semantic model and enforcement architecture.

Purpose

Authentication (COG-10) establishes who a caller is. Capabilities establish what they may do:

  • Least privilege — agents receive only the permissions their role requires
  • Transparent boundaries — agents are told what they can do, preventing trial-and-error discovery
  • Structural denial — denied operations return actionable errors, not ambiguous failures
  • Delegable authority — users can delegate scoped authority to agents or other users via UCAN tokens
  • Attenuation — delegated capabilities can only narrow, never widen, the grantor's authority

Terminology

See COG-1: Architecture for Grid terminology and COG-11: Agent Lifecycle for agent state.

A Capability is a {with, can} pair granting an ability on a resource.

An Attenuation is a vector of capabilities assigned to an agent, restricting its operations to those covered by at least one capability in the vector.

A UCAN (User Controlled Authorisation Network) is a signed token encoding a delegation of capabilities from an issuer to an audience.

Capability Structure

A capability is a map with two required fields:

{ "with": "w/decisions/", "can": "crud/write" }
FieldTypeDescription
withstringResource — a path prefix identifying the scope of access
canstringAbility — a slash-delimited permission in the ability hierarchy

An agent's capabilities are expressed as a vector of capability maps in the caps field of the agent record (COG-11):

"caps": [
{ "with": "w/vendor-records/", "can": "crud/read" },
{ "with": "w/enrichments/", "can": "crud" },
{ "with": "g/helper", "can": "agent/message" }
]

Null vs Empty

  • Null caps (field absent or null): unrestricted access — no capability checking is performed
  • Empty caps ([]): deny-all — every operation is denied

This distinction is critical. A newly created agent with no caps field has full access. An agent with caps: [] can do nothing.

Resource Matching

The with field is a path prefix. A capability's resource covers a request's target resource if:

  1. The capability resource equals the request resource, OR
  2. The capability resource is a prefix of the request resource

Examples:

Capability withRequest resourceCovered?
w/vendor-recordsw/vendor-recordsYes (exact match)
w/vendor-recordsw/vendor-records/acmeYes (prefix)
w/vendor-recordsw/vendor-records/acme/contactYes (prefix)
w/vendor-recordsw/other-dataNo
w/w/anything/at/allYes (covers entire workspace)
""any resourceYes (wildcard)

Resource Extraction

For each operation, the target resource is derived from the invocation input:

Operation typeResource derivation
Workspace operations (covia:read, covia:write, etc.)The path parameter
Agent operations (agent:request, agent:create, etc.)g/<agentId> from the agentId parameter
Grid operations (grid:run, grid:invoke)No resource-specific check

Operations without a derivable resource are checked only for ability coverage, not resource scope.

Cross-User Resources

Resources may include a full DID URL for cross-user access:

{ "with": "did:key:zAlice.../w/shared-data", "can": "crud/read" }

This enables capability delegation across user boundaries — see UCAN Delegation.

Ability Hierarchy

Abilities are slash-delimited strings forming a hierarchy. A capability's ability covers a requested ability if:

  1. The capability ability equals the requested ability, OR
  2. The capability ability is a prefix of the requested ability

The wildcard ability "*" covers any requested ability.

Standard Abilities

crud                    (any CRUD operation)
├── crud/read (read, list, slice, inspect)
├── crud/write (write, append)
└── crud/delete (delete)

agent (any agent operation)
├── agent/create
├── agent/request
├── agent/message
└── agent/fork

invoke (operation execution)

asset (asset operations)
└── asset/store

secret (credential access)
└── secret/decrypt

ucan (token delegation)
├── ucan/delegate
└── ucan/revoke

Operation-to-Ability Mapping

Each operation maps to a required ability:

OperationRequired Ability
covia:read, covia:list, covia:slice, covia:inspectcrud/read
covia:write, covia:appendcrud/write
covia:deletecrud/delete
agent:create, agent:request, agent:message, agent:forkagent/*
grid:run, grid:invokeinvoke
asset:storeasset/store
secret:extractsecret/decrypt
ucan:issueucan/delegate

A capability with ability crud covers crud/read, crud/write, and crud/delete. A capability with ability crud/read does NOT cover crud/write.

Enforcement

Enforcement Point

Capability checking occurs before an operation is dispatched to its adapter. The enforcement point is the job invocation layer:

  1. Extract the caller's capability vector from the request context
  2. If caps is null, allow (unrestricted)
  3. Extract the target resource from the operation input
  4. Determine the required ability from the operation
  5. Check whether any capability in the vector covers the request
  6. If no capability covers the request, deny with a structured error

Matching Algorithm

For a request with resource R and ability A, check each capability C in the agent's caps vector:

ALLOW if any C where:
C.with is a prefix of R (or C.with == "")
AND
C.can is a prefix of A (or C.can == "*")

DENY otherwise

First matching capability allows the operation. Order does not matter.

Agent Tool Calls

In the agent architecture (COG-11), capability checking applies at the Level 2 (domain logic) tool dispatch point:

  1. Agent's LLM requests a tool call
  2. Level 2 adapter resolves the tool to a grid operation
  3. Capability check against the agent's caps
  4. If denied, return error to LLM (operation is not executed)
  5. If allowed, invoke the operation

Level 3 (LLM call) is NOT capability-gated — the LLM invocation itself is always permitted. Only the agent's tool calls are restricted.

Disclosure

Capabilities MUST be disclosed to agents in their system prompt so the LLM knows its boundaries. The disclosure section is formatted as:

## Your capabilities (caps)
- crud/write on w/decisions/
- crud/read on w/
- agent/message on g/Alice

Tool calls outside these capabilities will fail with a "Capability denied" error.
Retrying the same call does not help — the denial is structural.

Disclosure MUST be refreshed every turn from the current agent configuration. Updates to an agent's caps take effect immediately without requiring a restart.

Denial Messages

When an operation is denied, the error message MUST:

  1. Name the denial — identify it as a capability denial
  2. Specify the requirement — operation name, required ability, target resource
  3. List available capabilities — the agent's actual caps in compact format
  4. Guide behaviour — state that retrying will not succeed and the denial is structural

Example:

Capability denied: v/ops/covia/write requires crud/write on w/audits/INV-123.
Your capabilities are: crud on w/decisions/, crud/read on w/.
Retrying the same call will not succeed — the denial is structural.

This design prevents LLM agents from looping on impossible operations by making boundaries actionable information.

UCAN Delegation

Capabilities are delegated via UCAN (User Controlled Authorisation Network) tokens — signed JWTs encoding a chain of authority from the resource owner to the delegate.

Token Structure

A UCAN token contains:

FieldDescription
issIssuer DID (who is delegating)
audAudience DID (who receives the delegation)
expExpiry timestamp
attAttenuations — vector of {with, can} capabilities
prfProof chain — vector of parent UCAN tokens

Issuance

Tokens are issued via the ucan:issue operation:

{
"operation": "ucan:issue",
"input": {
"audience": "did:key:z6Mk...",
"expiry": 1718000000000,
"attenuations": [
{ "with": "w/shared-data/", "can": "crud/read" }
]
}
}

The venue signs the token with its own keypair. The issuer is the venue DID (Phase C1). Attenuations MUST be within the caller's own namespace.

Verification

On each request, UCAN tokens are verified:

  1. Signature verified against issuer's public key
  2. Expiry checked: exp >= now
  3. Audience DID matched: aud == caller DID
  4. Each capability in att checked for coverage
  5. If proof chain is non-empty, each parent UCAN verified recursively

Attenuation Rule

Delegated capabilities can only narrow the grantor's authority:

  • The delegate's with MUST be equal to or a sub-path of the grantor's with
  • The delegate's can MUST be equal to or a sub-ability of the grantor's can

For example, a grantor with {with: "w/", can: "crud"} can delegate:

  • {with: "w/reports/", can: "crud/read"} — narrower on both resource and ability
  • {with: "w/reports/", can: "crud"} — narrower on resource, same ability

But cannot delegate:

  • {with: "s/secrets/", can: "crud/read"} — different resource, not a sub-path of w/

Agent Capability Models

User-Scoped (Current)

The agent has no independent identity. It acts under its owner's DID with attenuated capabilities:

  • Venue issues a scoped capability set at agent creation
  • Caps are stored in the agent record alongside config
  • Tool calls carry the owner's DID with the agent's restricted capability set
  • The venue enforces capability checks on every tool invocation

Independent (Planned)

The agent has its own Ed25519 keypair and DID:

  • Agent can receive delegations from multiple users
  • Agent signs its own UCANs for sub-delegation to child agents
  • Tool calls carry the agent's DID and proof chain
  • Full UCAN verification with delegation chain walking

Security Considerations

Principle of Least Privilege

Agents SHOULD be configured with the minimum capabilities required for their role. The AP demo illustrates this:

  • Alice (scanner): no workspace access, structured output only
  • Bob (enricher): read vendor records, write enrichments
  • Carol (approver): read all workspace, write decisions only

Empty Caps as Sandbox

Setting caps: [] creates a fully sandboxed agent that cannot invoke any tools. Combined with defaultTools: false, this produces a pure reasoning agent with no side effects.

Capability Escalation

Agents with agent/create capability can create child agents. Venues MUST ensure that child agents cannot be created with broader capabilities than their parent. The attenuation rule applies transitively.

Disclosure Accuracy

The capability disclosure in the system prompt MUST accurately reflect the enforced capabilities. Discrepancies between disclosed and enforced capabilities would cause agents to attempt operations they believe are permitted but that will be denied.

Examples

Read-Only Analyst

"caps": [
{ "with": "w/", "can": "crud/read" }
]

Can read any workspace path. Cannot write, delete, or invoke agent operations.

Scoped Worker

"caps": [
{ "with": "w/vendor-records/", "can": "crud/read" },
{ "with": "w/enrichments/", "can": "crud" },
{ "with": "g/helper", "can": "agent/message" }
]

Can read vendor records, perform full CRUD on enrichments, and send messages to the "helper" agent.

Manager with Delegation

"caps": [
{ "with": "w/", "can": "crud" },
{ "with": "g/", "can": "agent" }
]

Full workspace access and full agent management. Can create, request, message, and fork any agent.