ExplanationUnderstand the concepts

Understanding agent registration

Agent registration is the mechanism that turns an independently-built agent into something the orchestrator can discover and route requests to. Agent Console uses a contract-driven approach: each agent describes itself, publishes that description at a well-known location, and a seed process makes it visible to the orchestrator. Understanding this mechanism is the foundation for adding new agents, debugging registration issues, and writing agent contracts that hold up in production.

What is the agent contract

An agent contract is a self-description that an agent publishes about itself. Agent Console uses the standard A2A AgentCard (version 0.3) as its contract, so any A2A-compliant tooling can read it.

The card declares:

  • Identity: the agent’s name, description, version, and optional provider.

  • Reachability: the url the agent is served at, its transport, and any additionalInterfaces.

  • Skills: the discrete units of work the agent can perform, each with an id, name, description, and tags.

  • Exchange formats: the defaultInputModes and defaultOutputModes the agent accepts and produces, expressed as MIME types.

  • Capabilities: protocol-level features the agent supports, such as streaming.

  • Security schemes: how a caller authenticates to the agent, if it requires authentication.

The card deliberately omits some things. It does not list the tools an agent may call or the permissions it holds. Those are governed separately, through the agent’s LiteLLM virtual key, and are owned by the team that builds the agent. Keeping tool access out of the contract means the orchestrator never has to cross-check tool calls against a declaration; the virtual key is the single source of truth for what an agent is allowed to do.

For the complete field-by-field schema, see Agent contract specification.

How self-registration works

Each agent serves its own contract at a well-known URL: /.well-known/agent-card.json. This convention means the orchestrator never needs to be told where to find an agent’s description; if the agent is reachable on the network, its contract is reachable too. Each agent implements this route itself. Earlier A2A releases wired the route up automatically through the SDK’s A2AExpressApp helper, but that helper is deprecated in v0.3, so agents now register the route explicitly.

A minimal contract looks like this:

{
  "protocolVersion": "0.3.0",
  "name": "Copywriter Agent",
  "description": "Generates marketing copy from a structured brief.",
  "url": "http://localhost:3001/",
  "preferredTransport": "JSONRPC",
  "version": "1.0.0",
  "capabilities": { "streaming": true },
  "defaultInputModes": ["text/plain"],
  "defaultOutputModes": ["text/plain"],
  "skills": [
    {
      "id": "generate-copy",
      "name": "Generate copy",
      "description": "Produces marketing copy from a structured brief.",
      "tags": ["copywriting", "marketing"]
    }
  ]
}

Registration itself is driven by a seed process. The seed fetches each agent’s agent-card.json and upserts the contract into the orchestrator’s agent registry. Running the seed repeatedly with the same contract is safe and produces the same result, so registration is idempotent: re-running it after a contract change updates the registry without creating duplicate entries.

In local development, the seed writes directly to the orchestrator’s database and requires no authentication.

Production registration currently requires a valid Keycloak JWT from the user triggering it. This is an interim arrangement. The intended approach is to drive registration from CI using a service-to-service token, rather than a human user’s credentials, and this is expected to change.

The role of the agent registry

The agent registry is the orchestrator’s lookup table of available agents. When a request arrives, the orchestrator consults the registry to identify which agent, or combination of agents, can satisfy it, and routes accordingly.

The registry is what makes the hub-and-spoke architecture work. The orchestrator acts as the hub because it holds the registry, and domain agents act as spokes because they are discoverable only through it. See Agent Console architecture for a fuller discussion of how the hub coordinates work across registered agents.

The orchestrator’s runtime validation is deliberately narrow. It checks that the responses it receives from an agent are well-formed A2A responses. It does not validate the content of those responses, and it does not police an agent’s tool calls against its contract. The contract is used to discover and route, not to gate every request.

Why contract-driven registration

Agent Console could have used a central configuration file maintained by the orchestrator team, listing every agent and what it can do. Contract-driven self-registration was chosen instead for three reasons.

Extensibility. Teams across Storyteq can build and deploy new agents without modifying core orchestrator code. A new agent appears in the registry as soon as it is seeded; the orchestrator did not need to know about it in advance.

Decoupling. The orchestrator depends on what an agent declares, not how it is implemented. Agents can change their internals freely as long as their contract continues to describe their behaviour accurately.

Standards-based interoperability. Because the contract is the open A2A AgentCard, agents and tooling that speak A2A interoperate without bespoke integration. Discovery is a property of a published standard rather than of Agent Console-specific glue.

The trade-off is that self-description requires discipline. The orchestrator routes on what an agent declares, not on what it can actually do. A contract that misstates the agent’s reachable URL, or describes skills the agent does not perform, causes routing failures that surface only at request time.

What registration is not

Registration is a narrow concern. It does not cover the following:

  • Deployment. Registration tells the orchestrator that an agent exists. Deploying the agent, which means putting it on the network so its agent-card.json is actually reachable, is a separate step.

  • Authentication between agents. The registry stores contracts; it does not establish trust relationships between agents at runtime.

  • Health checking. The orchestrator does not infer that a registered agent is alive or healthy. Nothing currently removes a registry entry when an agent is taken down, so stale entries can persist until they are cleaned up by hand.

  • Runtime negotiation. Contracts are declared statically and consulted at request time. Agents do not negotiate capabilities on a per-request basis.

Keeping these concerns out of registration keeps the contract small and stable.