A2A Protocol
Claix as an A2A agent
Endpoint
https://claix.dev/a2aClaix exposes an Agent-to-Agent (A2A) agent so other agents can call it with JSON-RPC 2.0, without going through MCP or rewriting the REST API. It reuses the same extraction, query, and schema operations. Skills are generated from openapi.yaml.
Protocol endpoint: https://claix.dev/a2a. Public Agent Card: https://claix.dev/.well-known/agent.json (also at https://claix.dev/.well-known/agent-card.json).
1. Public routes
| Method | Path | What it does |
|---|---|---|
| GET | /.well-known/agent.json | Agent Card (discovery). No API key. |
| GET | /.well-known/agent-card.json | Same Agent Card (official @a2a-js/sdk path). |
| POST | /a2a | A2A JSON-RPC 2.0. Requires an API key. |
Point the inspector or A2A client at the site origin (https://claix.dev), not at /a2a, so it can resolve the Agent Card under /.well-known/. The card url / supportedInterfaces fields point to https://claix.dev/a2a.
2. Authentication and limits
On every POST /a2a send the same API key as REST:
x-api-key: <YOUR_API_KEY>
Alternative: Authorization: Bearer <YOUR_API_KEY>. Missing key: JSON-RPC -32001 and HTTP 401. Invalid key or inactive account: the same code. Limit: 60 requests per minute per API key (HTTP 429, Retry-After).
The Agent Card is public. Messages, DataParts, and any caller agent card are untrusted input and are validated before any business logic runs.
3. Agent Card
The card declares name: Claix, the JSON-RPC URL, capabilities.pushNotifications: true, streaming: false, and the 20 skills. Each skill's input schema (OpenAPI parameters, with file_base64 / file_path instead of multipart file) lives in the https://claix.dev/a2a/extensions/openapi-skills extension.
If OpenAPI changes, regenerate skills with npm run a2a:skills. Do not edit them by hand.
4. How to use it
- Fetch the Agent Card and pick a skill by
id. POST https://claix.dev/a2awithmethod: "message/send".- If you already have typed parameters, send a JSON DataPart with
"skill": "<id>". That path is deterministic — no language model. - If you only have ambiguous text, send a TextPart. Gemini 3.6 Flash chooses the skill and arguments from the same schemas.
- Reuse the same
contextIdon follow-up messages to keep the thread (stored inconversaciones).
Common JSON-RPC methods:
| Method | Use |
|---|---|
| message/send | Create or continue a task. |
| tasks/get | Read the status of an existing task. |
| tasks/cancel | Cancel a running task. |
| tasks/pushNotificationConfig/set | Register the webhook for long-running task results. |
There is no message/stream / SSE. Long tasks do not keep the HTTP connection open.
5. DataPart vs TextPart
| Input | Behavior |
|---|---|
| DataPart with a known skill | Routes straight to the internal operation (same logic as REST). |
| DataPart without skill | Task input-required: tells the caller which skill id to send. |
| Unknown skill or corrupt parameter | JSON-RPC -32602 Invalid params, naming the field and reason. |
| Recoverable missing field (space_id, schema_id, file…) | input-required, not an error. The calling agent can supply it. |
| Natural-language TextPart | Gemini 3.6 Flash picks skill + params. Only LLM hop in the router. |
DataPart example: {"skill":"extract-pdf","schema_id":"<uuid>","file_base64":"<base64>"}. REST multipart file becomes file_base64 or file_path (public https URL).
6. Task states and response formats
A successful message/send returns a JSON-RPC result Task (id, contextId, status.state, artifacts).
| State | When |
|---|---|
| completed | Fast task finished in the same response (get-document, query-document, list/create/delete schema, space, or document). |
| working | Long task queued: extract-*, agent-extract-*, convert-json-to-excel, query-space. Result arrives via push webhook. |
| input-required | A parameter the caller can supply is missing (e.g. space_id). |
| failed | The Claix business operation returned a non-2xx. |
| canceled | The caller canceled the task. |
Business output is a JSON artifact, not SSE:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"id": "<taskId>",
"contextId": "<contextId>",
"status": { "state": "completed" },
"artifacts": [
{
"name": "list-schemas-result",
"parts": [{ "kind": "data", "data": { "success": true, "schemas": [] } }]
}
]
}
}Protocol errors (before a task is created):
| HTTP | code | Meaning |
|---|---|---|
| 401 | -32001 | Missing or invalid API key. |
| 429 | -32000 | Rate limit. See Retry-After. |
| 400 | -32602 | Invalid params: wrong type or corrupt value. |
{
"jsonrpc": "2.0",
"id": 1,
"error": { "code": -32602, "message": "Invalid params: schema_id — …" }
}7. Long tasks and push notifications
Extracting a PDF, agent-mode reasoning, or querying a space_id with many documents does not wait on the HTTP connection. The first response stays working. Set an A2A webhook (tasks/pushNotificationConfig/set) to receive the final Task (completed or failed) with the artifact.
capabilities.pushNotifications is true. Do not use SSE streaming for these operations.
8. Conversation and contextId
The A2A contextId is the thread across tasks. Claix stores it in conversaciones (context_id, user_id, last_task_id, last_activity_at). Reuse the same contextId on every message/send in that dialogue.
9. Skills (from OpenAPI)
Each relevant OpenAPI operation is a skill. A DataPart must include "skill": "<id>".
| A2A skill | OpenAPI operationId | REST endpoint |
|---|---|---|
| extract-excel | excelToJson | POST /excel-json |
| convert-json-to-excel | jsonToExcel | POST /json-excel |
| extract-pdf | pdfToJson | POST /pdf-json |
| extract-doc | docToJson | POST /doc-json |
| extract-img | imgToJson | POST /img-json |
| extract-txt | txtToJson | POST /txt-json |
| get-document | getDocument | GET /get-document/{document_id} |
| query-document | documentContextAsk | POST /document-context/{document_id} |
| query-space | spaceContextAsk | POST /space-context/{space_id} |
| create-space | createSpace | POST /create-space |
| delete-space | deleteSpace | DELETE /delete-space/{space_id} |
| delete-document | deleteDocument | DELETE /delete-document/{document_id} |
| agent-extract-excel | agentExcelToJson | POST /agent/excel-json |
| agent-extract-pdf | agentPdfToJson | POST /agent/pdf-json |
| agent-extract-doc | agentDocToJson | POST /agent/doc-json |
| agent-extract-img | agentImgToJson | POST /agent/img-json |
| agent-extract-txt | agentTxtToJson | POST /agent/txt-json |
| list-schemas | listSchemas | GET /schemas |
| create-schema | createSchema | POST /create-schema |
| delete-schema | deleteSchema | POST /delete-schema |
10. Clients
- Official TypeScript SDK:
@a2a-js/sdk - Inspector: a2aproject/a2a-inspector against
https://claix.dev - Any A2A 0.3 / 1.0 JSON-RPC client with push notifications
MCP and A2A are separate interfaces. MCP remains at https://claix.dev/mcp. This agent does not call the MCP server.