Agentic Workforce ME Developer PortalDocs 1.7 · Widget 0.5.0

Backend integration

Call a platform agent from Foundry, Copilot Studio or watsonx

Expose an agent over A2A v1.0 / v0.3: the well-known Agent Card, bearer authentication with an API key, message:send and JSON-RPC examples, task states and the input-required approval pause.

An agent whose published manifest sets a2a.expose: true is served as an A2A server — a public Agent Card, message:send, task lookup and cancel, in both the A2A v1.0 and v0.3 wire generations — at https://<api-host>/v1/a2a/<agentId>. Microsoft Foundry, Copilot Studio, IBM watsonx Orchestrate and any other A2A client register that URL and call it with a platform API key. Every call is a real, metered, audited run; an approval pause surfaces as the A2A task state input-required. The other direction — Agentic Workforce ME calling their agents — is Connect an external agent.

1. Expose the agent

In the manifest, turn on a2a.expose, list the caller tenant ids in allowed_callers (silence is deny; allow_any_caller is the explicit opt-in for any authenticated caller) and optionally name the card and its skills. Publish the version.

JSON
{
  "a2a": {
    "expose": true,
    "allowed_callers": ["<caller tenant id>"],
    "allow_any_caller": false,
    "card": {
      "name": "Contract Risk Analyst",
      "description": "Reviews a contract and lists risk clauses.",
      "skills": ["analyze", "summarize"]
    }
  }
}

Then create an API key for the caller tenant (Admin → Settings → API keys, or POST /v1/api-keys — see API keys & authentication). Keys carry the tenant, so no X-Tenant-Id header is needed. A partner organisation therefore needs an account and a key on this deployment: there is no OAuth authorization server for inbound A2A yet (roadmap, Phase 3).

2. The well-known card

Shell
curl -sS "https://<api-host>/v1/a2a/<agentId>/.well-known/agent-card.json"
# add -H "A2A-Version: 0.3" for the v0.3 card shape
Request headerCard served
nonev1.0 card — supportedInterfaces = HTTP+JSON 1.0, JSON-RPC 1.0 and JSON-RPC 0.3, all at one base URL; securitySchemes.bearer; capabilities {streaming:false, pushNotifications:false}; signatures: [].
A2A-Version: 0.3v0.3 card — url, protocolVersion: '0.3', preferredTransport: 'JSONRPC', additionalInterfaces (HTTP+JSON), security.

3. Authenticate

Every callable route needs Authorization: Bearer hive_…. The authenticated tenant must be in allowed_callers:

FailureResponse
no / bad credential401 UNAUTHORIZED
tenant not allowed by the manifest403 A2A_CALLER_FORBIDDEN
agent not exposed / unknown404 NOT_FOUND

Task reads are caller-scoped: only the tenant that created a task can fetch or cancel it.

4. Send a message

Shell
curl -sS -X POST "https://<api-host>/v1/a2a/<agentId>/message:send" \
  -H "Authorization: Bearer hive_…" \
  -H "A2A-Version: 1.0" \
  -H "Content-Type: application/json" \
  -d '{
    "message": {
      "role": "ROLE_USER",
      "messageId": "m-001",
      "contextId": "conv-42",
      "parts": [{ "text": "Review clause 12 for liability risk." }]
    },
    "configuration": { "returnImmediately": false }
  }'
  • Parts: {text} and {data} (JSON-stringified into the prompt); file parts are ignored. No text/data part → 400 A2A_CONTENT_TYPE_NOT_SUPPORTED; over 16 000 characters → 413 A2A_MESSAGE_TOO_LARGE.
  • returnImmediately: false (1.0) / blocking: true (0.3) — the default — runs the agent inline and returns the final task, or an input-required task when an approval paused it. Non-blocking returns submitted; poll GetTask / tasks/get.
  • contextId is echoed back (the run's thread id when it has one); messageId, contextId and metadata are stored on the run input and never shown to the model.
  • Tasks are one-shot: a message carrying taskId is refused (501 / -32004). One JSON-RPC endpoint dispatches by method name: SendMessage, GetTask, CancelTask (1.0) and message/send, tasks/get, tasks/cancel (0.3). Streaming (message:stream, SSE) and push-notification configs ship in the same release as this page (before that they answer -32004 / -32003); list methods answer -32004.
Shell
# poll a task (always send the version header)
curl -sS "https://<api-host>/v1/a2a/<agentId>/tasks/<taskId>" \
  -H "Authorization: Bearer hive_…" -H "A2A-Version: 1.0"

# cancel
curl -sS -X POST "https://<api-host>/v1/a2a/<agentId>/tasks/<taskId>:cancel" \
  -H "Authorization: Bearer hive_…" -H "A2A-Version: 1.0"

5. Task states

Run statusA2A 0.3A2A 1.0Meaning
queuedsubmittedTASK_STATE_SUBMITTEDnon-blocking send answered here; poll
runningworkingTASK_STATE_WORKING
waiting_approvalinput-requiredTASK_STATE_INPUT_REQUIREDan approval is pending — status.message names the tool and approval id
succeededcompletedTASK_STATE_COMPLETEDartifacts[0] = { name: "output", parts: [{ text }] }
failedfailedTASK_STATE_FAILEDstatus.message = <code>: <message>
cancelledcanceledTASK_STATE_CANCELEDCancelTask / tasks/cancel, or a platform-side cancel
expiredfailedTASK_STATE_FAILEDthe approval SLA elapsed

input-required is an approval

When the agent's HITL policy pauses the run, the task parks in input-required until a person decides it in Operate → Approvals or via POST /v1/approvals/:id/decision (Human-in-the-loop approvals). The A2A caller cannot answer it — by design, a checkpointed interrupt resumes only through the approvals decision path. Poll until the state is completed, failed or canceled; CancelTask on a paused task voids the pending approvals.

6. Register in the vendors' orchestrators

Every registration needs the same two things: the A2A base URL https://<api-host>/v1/a2a/<agentId> (append /.well-known/agent-card.json for the card) and an API key sent as a bearer. The vendor pages linked below are authoritative for their screens.

Microsoft Foundry Agent Service — A2A tool

Add an Agent-to-agent (A2A) tool to the Foundry agent, pointing at the card or endpoint URL, with the API key as the tool's bearer secret. Foundry speaks A2A 1.0 (JSON-RPC) and 0.3; both are served at that base. Expect text in, text out, no streaming.

Microsoft Copilot Studio — agent over A2A

Connect to an agent over A2A with the endpoint URL and API-key / bearer authentication (header Authorization, value Bearer hive_…). Copilot Studio's auto-discovery looks for /.well-known/agent.json, which is not served — fill the card / endpoint fields explicitly.

IBM watsonx Orchestrate — discover and import

Orchestrate imports A2A 0.3.0 cards and attaches the agent as a collaborator of a native agent (ADK: connect external agents). Create a connection whose secret is the API key, then:

Shell
orchestrate agents discover \
  -u "https://<api-host>/v1/a2a/<agentId>/.well-known/agent-card.json" \
  --app-id <connection holding the API key as a bearer token>

Orchestrate then calls the JSON-RPC 0.3 interface listed in the card. If the importer sends no A2A-Version header it receives the 1.0 card (see the warning in section 2).

7. Exposing agents as MCP tools (POST /v1/mcp)

The same exposed agents are also offered to MCP clients — Claude's MCP connector, OpenAI hosted MCP tools, Copilot Studio MCP tools, Foundry Toolboxes — as tools over streamable HTTP. There is no separate flag: an agent is an MCP tool iff it is A2A-exposed and allowed_callers admit the caller. Ships in the same release as this page.

ItemValue
EndpointPOST /v1/mcp — JSON-RPC initialize, ping, tools/list, tools/call; stateless (no Mcp-Session-Id); GET → 405, DELETE → 204.
Tool nameshive.<agent-slug> for the whole agent, plus hive.<agent-slug>.<skill-id> per named card skill.
Input / output{ task, context?, thread_id? } (task ≤ 16 000 chars) → { text, run_id, status, thread_id }. A call is an A2A blocking SendMessage: a real, metered, audited run.
ApprovalsA run paused for approval comes back as a tool error naming the approval id; it resumes only through POST /v1/approvals/:id/decision.
AuthAuthorization: Bearer with an API key (hive_…) or an access token from the tenant's configured OIDC identity provider (aud = this resource or the tenant client id). Every 401 carries WWW-Authenticate: Bearer realm="hive", resource_metadata=….
Discovery (RFC 9728)GET /.well-known/oauth-protected-resource[/v1/mcp] resource, scopes_supported: ["hive:agents:invoke"], the tenant IdP as authorization server; name the tenant with ?tenant=<slug|id> or X-Tenant-Id.