Integrations
The platform API is not only a dashboard backend. It also exposes protocol and integration boundaries that let Agirunner participate in larger systems.
Status note
Remote MCP management is already part of the main supported control plane. A2A and ACP endpoints also exist today, but they are still in active development. The current implementation exposes real routes and service logic for both, but they are not yet presented as fully production-hardened or extensively compatibility-tested protocol surfaces.
Main Integration Areas
Section titled “Main Integration Areas”- remote MCP server management
- A2A task ingress and status
- ACP session-oriented execution
- OAuth and webhook support flows
Remote MCP Servers
Section titled “Remote MCP Servers”These routes manage external MCP servers that Agirunner can verify and grant into specialist tool surfaces.
Main routes
Section titled “Main routes”GET /api/v1/remote-mcp-serversPOST /api/v1/remote-mcp-serversPUT /api/v1/remote-mcp-servers/:idPOST /api/v1/remote-mcp-servers/:id/reverifyPOST /api/v1/remote-mcp-servers/:id/oauth/reconnectPOST /api/v1/remote-mcp-servers/:id/oauth/disconnect
Create request
Section titled “Create request”POST /api/v1/remote-mcp-servers
Scope: admin
Representative body:
{ "name": "Linear MCP", "description": "Remote MCP surface for issue and project operations.", "endpointUrl": "https://mcp.example.com", "transportPreference": "auto", "callTimeoutSeconds": 300, "authMode": "parameterized", "enabledByDefaultForNewSpecialists": false, "parameters": [ { "placement": "header", "key": "Authorization", "valueKind": "secret", "value": "Bearer ..." } ]}Response shape
Section titled “Response shape”The route returns the verified server record, including verification status, discovered capability snapshots, and the resolved transport choice.
Remote MCP server fields
Section titled “Remote MCP server fields”| Field | Contract | Meaning |
|---|---|---|
name / description | string | Operator-facing identity for the remote server. |
endpointUrl | URL string | Base endpoint the platform will verify and call. |
transportPreference | enum | Preferred remote transport mode, or auto to let verification choose. |
callTimeoutSeconds | integer | Upper bound on a single remote call. |
authMode | enum-like string | How auth material is supplied to the remote server. |
enabledByDefaultForNewSpecialists | boolean | Whether newly created specialists should automatically see this server as available. |
parameters | structured object[] | Header, query, or other auth/config parameters sent to the remote server. Secret-bearing values are sanitized on readback. |
The A2A surface is a thin task-ingress facade over the platform task broker.
Agent card
Section titled “Agent card”GET /.well-known/agent.json
Representative response:
{ "protocol": "a2a", "protocol_version": "0.1", "name": "Agirunner", "description": "A2A ingress and query facade over the Agirunner task broker.", "authentication": { "type": "bearer_api_key", "header": "Authorization" }, "capabilities": { "task_submission": true, "status_query": true, "streaming_updates": true }, "endpoints": { "submit_task": "https://example/api/v1/a2a/tasks", "get_task": "https://example/api/v1/a2a/tasks/{taskId}", "stream_task": "https://example/api/v1/a2a/tasks/{taskId}/events" }}Agent card fields
Section titled “Agent card fields”| Field | Contract | Meaning |
|---|---|---|
protocol / protocol_version | fixed string | Protocol identity this endpoint is advertising to external A2A clients. |
authentication | structured object | How the external caller is expected to authenticate. |
capabilities | structured object | High-level A2A capability flags currently exposed by the platform. |
endpoints | structured object | Concrete route templates external callers should use. |
Submit task
Section titled “Submit task”POST /api/v1/a2a/tasks
Scope: agent
Request body:
{ "task": { "id": "external-123", "title": "Review release blockers", "description": "Summarize open blockers and propose next actions.", "type": "analysis", "priority": "high", "workflow_id": "33333333-3333-3333-3333-333333333333", "workspace_id": "22222222-2222-2222-2222-222222222222", "role": "reviewer", "input": { "focus": "release blockers" }, "context": {}, "metadata": { "source": "external-system" } }}A2A task fields
Section titled “A2A task fields”| Field | Contract | Meaning |
|---|---|---|
task.id | string | Optional external task identifier from the caller. The platform stores it as protocol-ingress metadata rather than replacing the platform task id. |
task.title | string | Required user-facing task title. |
task.description | string | Main natural-language brief for the task. |
task.type | string | Optional external task type label. |
task.priority | string | Queue priority hint. Unsupported values normalize to normal. |
task.workflow_id | UUID | Optional existing workflow to attach the ingressed task to. |
task.workspace_id | UUID | Optional workspace context for the created task. |
task.role | string | Preferred specialist role name. |
task.input | arbitrary JSON object | Structured execution payload. |
task.context | arbitrary JSON object | Additional surrounding context. |
task.metadata | arbitrary JSON object | Extra caller annotations merged into protocol-ingress metadata. |
Response:
{ "data": { "id": "44444444-4444-4444-4444-444444444444", "status": "submitted", "title": "Review release blockers", "created_at": "2026-03-31T18:55:00.000Z", "updated_at": "2026-03-31T18:55:00.000Z", "result": null, "metadata": { "task_id": "44444444-4444-4444-4444-444444444444", "workflow_id": "33333333-3333-3333-3333-333333333333", "workspace_id": "22222222-2222-2222-2222-222222222222" } }}A2A response fields
Section titled “A2A response fields”| Field | Contract | Meaning |
|---|---|---|
id | server-generated | Platform task id, not the caller-supplied external id. |
status | enum-like string | A2A-facing mapped status derived from internal platform task state. |
result | arbitrary JSON value or null | Sanitized task output when available. |
metadata.protocol_ingress.external_task_id | string or null | Echo of the external caller’s original task id when one was supplied. |
metadata.task_id / workflow_id / workspace_id | UUID | Platform linkage ids to use in later Agirunner API calls. |
A2A task stream
Section titled “A2A task stream”GET /api/v1/a2a/tasks/:id/events
Scope: agent
SSE event shape:
id: 1234event: task.state_changeddata: {"task_id":"4444...","status":"working","created_at":"2026-03-31T19:10:00.000Z"}ACP supports session-oriented execution where the platform pairs a claimed task with an ACP session record.
Create or reuse session
Section titled “Create or reuse session”POST /api/v1/acp/sessions
Scope: agent
Request body:
{ "agent_id": "99999999-9999-9999-9999-999999999999", "worker_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "workflow_id": "33333333-3333-3333-3333-333333333333", "transport": "websocket", "mode": "session", "workspace_path": "/workspace", "metadata": { "client": "custom-acp-runner" }}ACP session fields
Section titled “ACP session fields”| Field | Contract | Meaning |
|---|---|---|
agent_id | UUID | ACP-registered agent that owns the session. The platform rejects agents not registered with protocol: acp. |
worker_id | UUID | Optional worker backing the ACP session. |
workflow_id | UUID | Optional workflow scope used when reusing long-lived ACP sessions. |
transport | enum | Session transport contract: stdio, http, or websocket. |
mode | enum | run for a per-task session, session for a reusable long-lived session. |
workspace_path | string | Preferred working directory the ACP client should use. |
metadata | arbitrary JSON object | Extra ACP-session metadata. The platform also adds protocol and capability information. |
Response:
{ "data": { "id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb", "agent_id": "99999999-9999-9999-9999-999999999999", "worker_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "workflow_id": "33333333-3333-3333-3333-333333333333", "transport": "websocket", "mode": "session", "status": "initializing", "workspace_path": "/workspace", "metadata": { "client": "custom-acp-runner" }, "last_heartbeat_at": "2026-03-31T18:55:00.000Z", "created_at": "2026-03-31T18:55:00.000Z", "updated_at": "2026-03-31T18:55:00.000Z", "reused": false }}ACP session response fields
Section titled “ACP session response fields”| Field | Contract | Meaning |
|---|---|---|
id | server-generated | ACP session record id. |
status | enum | Current session state, such as initializing, active, idle, or closed. |
last_heartbeat_at | server-generated | Most recent liveness update from the ACP client. |
reused | server-generated | Present when the platform is reporting whether this session was newly created or reused. |
Claim ACP task
Section titled “Claim ACP task”POST /api/v1/acp/claim
Scope: agent
Request body:
{ "agent_id": "99999999-9999-9999-9999-999999999999", "worker_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "routing_tags": [ "acp" ], "include_context": true, "session": { "transport": "websocket", "mode": "run" }}Success response:
{ "data": { "session": { "id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb", "status": "initializing" }, "task": { "id": "44444444-4444-4444-4444-444444444444", "title": "Review release blockers", "prompt": "Summarize open blockers and propose next actions.", "cwd": "/workspace", "input": {}, "context": {}, "file_references": [] } }}ACP claim fields
Section titled “ACP claim fields”| Field | Contract | Meaning |
|---|---|---|
routing_tags | string[] | Claim filter tags. Defaults to ['acp'] when omitted. |
include_context | boolean | Whether the claim response should include richer task context payloads. |
session.transport / session.mode | enum | Session contract to use if a new session must be created or an existing one reused. |
session.workspace_path | string | Optional override for the execution working directory. |
task.prompt | string | Prompt-like summary the ACP client should execute against. |
task.cwd | string or null | Working directory the ACP client should treat as current. |
task.file_references | structured object[] | Document-style references extracted from task context for ACP clients. |
As with normal claim routes, ACP claim can return 204 No Content when
no task is available.