Skip to main content

Agent Capability Plane

You are in the deep end

This page is the registry contract. Publishing as a transfer of ownership: operating model.

Publishers append a capability as id@version. A route refers to those versions. Runtime hydrates the whole pinned manifest once, at pin, then never re-reads the registry mid-loop.

This box sits with the Agent Plane, beside Control Plane and Data Plane. It is a catalogue of tools and child agents — not a third Front Door, not MCP list_tools, and not Shared Tools.

What it is​

Two kinds of capability:

  • domain — a governed business API the agent may invoke.
  • agent — start another catalogue route through the Front Door jobs API.

Kinds and schemas: capabilities.

What it owns​

OwnsDoes not own
Immutable id@version rows and manifestsClassify, pin, start
Hydrate reads at the pinned versionMid-loop tool dispatch

What it must not do​

  • Edit a published version. A fix is a new version.
  • Be called from the LangGraph loop on every tool turn.
  • Live in Shared. Memory, RAG, and Tools stay there.

How to talk to it​

Runtime GETs at pin. Publishers PUT a version. Fixtures: capability-account-fee-lookup.json, manifest-fee-explain.json.


Design notes​

Business problem​

Teams inline OpenAPI into manifests, or they bind latest, or they treat MCP list_tools as the enterprise catalog. The loop fetches tools when the model first names them. Parent AR POSTs Legal's activation_target. A published capability is mistaken for permission. Every domain republishes the same OCR API.

Key requirements​

IDRequirement (this box)
Locked-8Capabilities are references. Publishers append immutable id@version. AR hydrates the whole pinned manifest before the LLM.
Locked-8kind=agent invoke is API AFD jobs, not the callee AR.
FR-8 / FR-10LLM never sees {jobs_url} or activation_target. Jobs Authorization is the calling agent token. Child mints its robot.
—Route row still has no tools[]. Only a tool_manifest pointer.
—Publish is append-only. Overwriting 1.2.0 is not a version.

Hydrate is pin-time, not turn-time. Scale with new starts and catalog reads, not with loop steps.

Architecture​

Publishers append an immutable id@version. Developers refer from the tool manifest. AR hydrates the whole pinned manifest before the LLM. Invoke goes through PEP: domain APIs or API AFD jobs.

Editorial source

Three objects, two writers. Three moments — only the last is the AR loop.

Key technology decisions​

ChoiceWhy
Package versions, not live list_toolsExam and pin need a frozen schema. 1.2.0 never changes once published.
Manifest stores a reference, not "latest"Publishing 2.0.0 must not move fraud_investigate_v1.
Hydrate whole manifest at pinNo mid-loop registry GET. Cache (manifest_id, manifest_version).
Two kinds, one catalogdomain = governed business API. agent = start another catalogue row via API AFD.
PEP then invokeA published capability is not permission. Dual check still runs.
Registry with Agent PlaneSame band as catalogue. Shared stays Memory / RAG / Tools.

Expected outcomes​

  • Domain teams publish an API once; agent developers copy a ref.
  • A2A is a named tool on the parent manifest, same jobs contract as partners.
  • In-flight runs keep hydrated schemas if the registry later goes down.
  • Reviewers see which catalog versions moved in the manifest PR.

This box owns / does not own​

OwnsDoes not own
Immutable capability versions (schema, invoke, snippet, owner, status)Pin, start, PEP permit, dual check
Search / list for UI and CIRoute choice, classify, activation_target
Hydrate reads at pinLoop-time tool fetch, MCP server per internal API

If the registry dies: new runs cannot hydrate; in-flight pins still have schemas.


2. Job​

Three objects, two writers. The route row still has no tools[].

ObjectWho writes itWhat it holds
Capability versionPublisherOne immutable release: schema, invoke, snippet. ocr_extract@1.2.0 or start_contract_review@1.0.0
Tool manifestAgent developerReferences: id + version + pdp_action + risk_tier
Route rowPlatform / domaintool_manifest pointer. Still no inlined tools
MomentWhoWhat happens
PublishPublisherPipeline puts one version in the registry. Append-only.
ReferAgent developerCopies { "id", "version" } into their tool_manifest.
CallARAfter freeze: download the whole pinned manifest, hydrate every ref onto the run pin, then schemas only to the LLM. invoke runs after PEP.

Same freeze vs new route. A summarizer helper is a domain capability on this manifest. Legal MSA review is an agent-start capability. The second one's invoke is the API AFD jobs URL, not Legal's activation_target.


3. What a capability version is​

FieldWhy it exists
idStable name: ocr_extract or start_contract_review. Product, not vendor.
versionImmutable semver. 1.2.0 never changes once published.
kinddomain (business API) or agent (start another catalogue row).
descriptionWhat the agent developer (and later the model) reads.
input_schema / output_schemaJSON Schema. Becomes the tool schema on the run pin.
invokeAfter PEP. Domain: governed business API. Agent-start: POST {jobs_url} with a fixed route_id.
snippetCopy-paste example for the developer. Documentation, not runtime.
ownerThe team that may publish the next version.
statusdraft / published / deprecated. Manifests may reference published only.

Breaking the contract is a new major. Overwriting 1.2.0 is not a version.

Domain capability version (JSON)
{
"id": "ocr_extract",
"version": "1.2.0",
"kind": "domain",
"description": "Extract text from a document id.",
"input_schema": {
"type": "object",
"required": ["doc_id"],
"properties": { "doc_id": { "type": "string" } }
},
"output_schema": {
"type": "object",
"required": ["text"],
"properties": { "text": { "type": "string" } }
},
"invoke": {
"method": "POST",
"url": "https://api.internal/ocr/extract",
"auth": "domain-oauth"
},
"owner": "document-intel",
"status": "published"
}
Agent-start capability version (JSON)
{
"id": "start_contract_review",
"version": "1.0.0",
"kind": "agent",
"description": "Start governed Legal MSA review as a jobs run.",
"input_schema": {
"type": "object",
"required": ["document_id"],
"properties": {
"document_id": { "type": "string" },
"matter_id": { "type": "string" }
}
},
"output_schema": {
"type": "object",
"required": ["correlation_id"],
"properties": { "correlation_id": { "type": "string" } }
},
"invoke": {
"method": "POST",
"url": "https://api-afd.internal/v1/jobs",
"auth": "calling-agent-oauth",
"body": { "route_id": "contract_review" }
},
"owner": "legal-agents",
"status": "published"
}

4. Call another route​

If this run needs a separate catalogue row, that callee is a named tool on the parent manifest. The model may only propose that name. The tool's invoke is API AFD, same jobs contract as partners and Kafka.

Two gates, in order:

  1. Manifest + PEP (this freeze). No invoke_any_agent. A tool not on the pinned manifest never fires.
  2. API AFD (the child start). Entitle the user and record. Freeze Legal's agent_client_id. Async-start Legal AR. 202 + a new correlation_id.

The LLM never sees {jobs_url} or activation_target. Parent AR never POSTs Legal's AR. Chat AFD stays for humans. This caller is software, so it is the jobs fleet.

Parent freeze stays fraud_investigate. Child freeze is contract_review. Two tickets.

If Legal is only a stage on the same row (workflow_id), stay in parent AR — not this path.

Identity: jobs Authorization is the calling agent token. After freeze, Legal mints its robot. Three principals.


5. Context​

ActorRelationship
PublisherPipeline PUTs one version. Humans draft; CI sets status=published.
Agent developerCopies { id, version } into tool_manifest.
ARGET each ref once after downloading the pinned manifest. Loop does not call this box.
Registry UISearch, detail, version history. Not a channel API.
Shared PEPExecutes hydrated invoke after dual check. Not the registry.
Chat/UINone. Schemas never go to the browser as catalog JSON.

6. How a reference lands in the manifest​

StepWhat they do
1. FindSearch the registry. Copy references.
2. WriteEdit the manifest file. tools[] is name, capability_id, capability_version, pdp_action, risk_tier.
3. PRReviewers see which catalog versions moved. CI checks each ref exists and is published.
4. PinAFD freezes the route. First AR downloads that whole tool_manifest, hydrates every ref, then talks to the LLM.
5. CallProposal must match a hydrated name. PEP. Then invoke from the pin.
Parent manifest with domain tools and one agent-start (JSON)
{
"manifest_id": "fraud_investigate_v2",
"manifest_version": "2026.08.1",
"tools": [
{
"name": "search_transactions",
"capability_id": "search_transactions",
"capability_version": "1.4.0",
"pdp_action": "search_transactions",
"risk_tier": "low"
},
{
"name": "start_contract_review",
"capability_id": "start_contract_review",
"capability_version": "1.0.0",
"pdp_action": "start_contract_review",
"risk_tier": "high"
}
]
}

7. APIs​

The registry is not a channel API. UI, pipeline, and one hydrate at pin call it. The loop does not.

MethodPathWho / when
PUT/v1/capabilities/{id}/versions/{version}Pipeline (publish). UI (draft save). Existing published → conflict
GET/v1/capabilities/{id}/versions/{version}UI detail. AR hydrate (every ref, once)
GET/v1/capabilities/{id}/versionsUI version history
GET/v1/capabilities?q=UI search of published

AR start still goes to {activation_target} from Runtime §5. Agent-start invoke is a later POST to {jobs_url} on API AFD.


8. Deployment architecture​

ConcernStance
IngressInternal only. Not a channel API.
ScalePublish rate + pin hydrates (refs per new run). Does not grow with tokens in the loop.
CacheHydrated (manifest_id, manifest_version) if many runs share a pin. Do not resolve latest.
FailoverReads from replicas. In-flight AR pins do not need this box.
IsolationIndependent of Layer ② decide CPU.

9. Data architecture​

Indexes: unique (id, version). Search: status=published + text on id / description.

Consistency: Published versions are immutable. No latest pointer in runtime.

Retention: Append-only. Deprecated versions remain GET-able so old pins and exam still hydrate.


10. Sequence diagrams​

Happy path — hydrate at pin​

After AFD start, AR downloads the pinned manifest, GETs every id@version, writes schemas onto the run pin, then sends schemas only to the LLM.

Editorial source

Agent-start invoke (two gates)​

Parent AR proposes a named agent-start tool. PEP checks the pinned manifest, then POSTs API AFD. API AFD entitles the user and starts the child AR. Parent never POSTs the callee activation_target.

Editorial source

11. Failure and resilience​

FailureBehaviour
Registry down at pinNew runs fail hydrate. In-flight pins continue. Classify/decide unaffected.
Registry down mid-loopNo effect if hydrate already happened. Do not lazy-fetch.
Missing / draft refFail start. Do not skip the tool silently.
PEP denyNo invoke. Published ≠ permitted.
API AFD deny on agent-startChild does not start. Parent run handles the error.
Duplicate child startJobs idempotency_key on AR/AFD.

Anti-patterns: AR POSTs callee activation_target; invoke_any_agent; Chat AFD for A2A; lazy tool fetch; latest as a reference; user bearer as jobs Authorization.


12. Scaling​

Hydrate is pin-time, not turn-time. Scale with new starts and catalog reads, not with loop steps.

AxisGrows withScale signal
RegistryPublish rate + pin hydrates (refs per new run)Hydrate p99, catalog QPS
Tools / PEPIn-flight invokes (domain and agent-start)Per-capability latency / deny rate
API AFD (agent-start only)Child job POST RPS from ARSame jobs signals as partners

Agent Runtime · Agent Front Door · Agent Plane · Agent Audit · Capabilities · Enterprise Agent Fabric