Skip to content

@A2AAgent, @A2AExpose, a2aHttpListener & A2ACallerResolver

The @A2AAgent and @A2AExpose decorators, a2aHttpListener, and A2ACallerResolver ("@agboss/core/a2a") provide both the client and server sides of the multi-tenant Agent-to-Agent (A2A) and federated Agent Mesh protocol in AGBoss, enabling strongly typed cross-service workflow calls with signed MeshEnvelope budget, deadline, and call-chain propagation:

  • @A2AAgent (a2a/*.a2a-agent.ts) defines a typed contract client (extends A2AClient<InDto, OutDto>) for a remote A2A workflow (target: { application, start }, input, output, price?), registered in @Workflow({ providers: [RemoteA2AAgent] }) and injected into any @Tool or @Action via deps: [RemoteA2AAgent].
  • @A2AExpose (a2a/*.a2a-expose.ts) declares the @WorkflowStart entry points (exports: [Start]) that an @Application({ exposes: [AppA2AExpose] }) serves over A2A and exports in agboss describe --json for agboss check --federation.
  • a2aHttpListener(app, { expose, callerResolver, meshVerifier?, base }) and A2ACallerResolver<typeof StartClass> (a2a/*.a2a-caller-resolver.ts) serve an @A2AExpose contract over HTTP (POST <base>/execute, /resume, /cancel), resolving the authenticated tenant, ownerId, execution, and peer from an @Injectable() resolver in the DI container before reading any request body.

Complete @A2AAgent, @A2AExpose, A2ACallerResolver, a2aHttpListener & a2aServer example

Section titled “Complete @A2AAgent, @A2AExpose, A2ACallerResolver, a2aHttpListener & a2aServer example”

What options do @A2AAgent, @A2AExpose, and a2aHttpListener accept?

Section titled “What options do @A2AAgent, @A2AExpose, and a2aHttpListener accept?”
API / Decorator Option Type Required Description
@A2AAgent name string Yes Unique kebab-case identifier ending with -a2a-agent ([name.kind-suffix]).
@A2AAgent url string Yes Base URL of the remote A2A endpoint ("https://billing.internal.example.com/a2a"), serving POST <url>/execute, /resume, and /cancel.
@A2AAgent target { application: string; start: string } Yes Declared contract target ([a2a.target-required]), verified against peer snapshots by agboss check --federation.
@A2AAgent input / output DtoClass Yes Request and response DTO contracts validated on execute(input, call?) and exported with schemaHash in agboss describe --json.
@A2AAgent price Usd No Declared fallback cost per remote call (usd(0.002)); the step records the larger of price and a trusted peer’s signed MeshRunReport.
@A2AAgent deps readonly Token[] No Constructor dependencies (ExecutionContext, TenantContext, or @Injectable auth services) used inside protected override getHeaders().
@A2AExpose name / version / exports string / readonly StartClass[] Yes Declares the @WorkflowStart classes (-a2a-expose) that @Application({ exposes }) serves over A2A ([application.expose-unknown-start], [application.expose-unlisted]).
a2aHttpListener(app, options) expose Class Yes The @A2AExpose class listed in @Application({ exposes }) served at this A2A endpoint.
a2aHttpListener(app, options) callerResolver Class<A2ACallerResolver<TStart>> Yes An @Injectable() class listed in @Application({ providers }) or @Workflow({ providers }) ([a2a.caller-resolver-not-listed] if omitted).
a2aHttpListener(app, options) meshVerifier Class<MeshVerifier> No Optional @Injectable() service implementing verifyKeyOf(issuer) to resolve peer Ed25519 SPKI public keys dynamically alongside @Application({ mesh: { peers } }).
a2aHttpListener(app, options) base string No URL path prefix ("/a2a" by default).

A2ACallerResolution, A2ACallerRejectedError, a2aServer & the Signed Agent Mesh Envelope

Section titled “A2ACallerResolution, A2ACallerRejectedError, a2aServer & the Signed Agent Mesh Envelope”
Related Entity Import Path Purpose
A2ACallerResolution.resolved({ tenant, ownerId, execution, peer }) "@agboss/core/a2a" Returned by resolveCaller(request: A2ACallerRequest) to bind the verified tenant, ownerId (thread ownership), execution context values, and trusted peer.
A2ACallerResolution.unauthenticated({ reason, challenge? }) / .forbidden({ reason }) "@agboss/core/a2a" Rejects the request before reading the body or starting an execution with HTTP 401 (a2a.caller-unauthenticated) or HTTP 403 (a2a.caller-forbidden), thrown on the client as A2ACallerRejectedError.
A2ACallerRejectedError "@agboss/core/a2a" Thrown by A2AClient on 401 / 403: err.code is always "a2a.caller-rejected", err.httpStatus is 401 or 403, and err.wireCode carries the server’s specific rejection code ("a2a.caller-unauthenticated" or "a2a.caller-forbidden").
a2aServer({ expose, callerResolver, meshVerifier? }) "@agboss/core/testing" testWith fixture that serves the test’s app on 127.0.0.1:0 and returns { url } for new A2AClient({ url, headers }).
Agent Mesh Envelope (MeshEnvelope, agboss-mesh) "@agboss/core" JWS EdDSA (Ed25519) envelope header (_meta["agboss.dev/mesh"] over MCP, plus W3C traceparent) carrying origin (executionId, parentExecutionId, workflow, step.idempotencyKey), budget.remaining, deadline.remaining, and callChain (MeshHop[]), plus signed MeshRunReport spend attribution (ToolCallRecord.remote).
MeshLoopDetectedError & HopsLimitExceededError "@agboss/core" Thrown before executing a step when callChain contains the current (application, start) pair (limit.mesh-loop) or reaches @Application({ maxMeshHops }) (8 by default, limit.hops).
$ agboss check --federation <path...> & $ agboss hub CLI Verifies cross-repository @A2AAgent / @McpServer contracts against agboss describe --json snapshots (--federation) and renders the global Agent Mesh graph, cross-service execution trees, Progressive Crystallization Radar, and Blast Radius (agboss hub show --html / agboss hub ui).