A2A Protocol
TypeScript SDK support for A2A routing, direct task execution, and multi-agent delegation.
See A2A Architecture for protocol concepts.
A2AClient
A2AClient talks to the Sekuire API A2A endpoints and supports task routing, JSON-RPC task APIs, and SSE subscriptions.
import { A2AClient } from '@sekuire/sdk';
const client = new A2AClient({
baseUrl: 'https://api.sekuire.ai',
authToken: process.env.SEKUIRE_API_KEY!,
timeout: 30_000,
});
// Route by skill
const route = await client.sendBySkill({
skill: 'document:summarize',
message: {
role: 'user',
parts: [{ type: 'text', text: 'Summarize this incident report.' }],
},
traceId: 'trace-123',
});
// Poll final task
const task = await client.getTask(route.taskId);
console.log(task.status.state);
// Or stream updates
for await (const event of client.subscribe(route.taskId)) {
console.log(event.status, event.message?.parts);
}
Task endpoint auth behavior
For /api/v1/tasks/* endpoints used by delegation fallback:
tokenResolverruntime token (dynamic, preferred for SDK-managed agents).- Runtime token set with
setRuntimeToken(backward compatibility). - If
authTokenlooks like a JWT, it is sent asAuthorization: Bearer. - Otherwise,
authTokenis sent asX-API-Key(+X-Device-Fingerprint).
client.setRuntimeToken(process.env.SEKUIRE_RUNTIME_TOKEN!);
You can override fingerprint via deviceFingerprint in constructor or SEKUIRE_DEVICE_FINGERPRINT.
When a request uses a runtime token and gets a 401, onUnauthorized can refresh and retry once.
A2AServer
A2AServer is an in-memory JSON-RPC server implementation. You provide an agent card and skill handlers, then wire it to your HTTP framework.
import express from 'express';
import type { AgentCard } from '@sekuire/sdk';
import { A2AServer } from '@sekuire/sdk';
const card: AgentCard = {
agentId: 'sekuire:acme:analysis-agent',
name: 'Analysis Agent',
description: 'Analyzes logs and incidents',
version: '1.0.0',
protocolVersions: ['0.2'],
capabilities: {
streaming: true,
pushNotifications: false,
extendedAgentCard: false,
},
skills: [
{ id: 'incident:summarize', name: 'Incident Summarizer' },
],
url: 'https://agent.example.com/a2a',
};
const server = new A2AServer({
card,
handlers: {
'incident:summarize': async (message) => ({
role: 'agent',
parts: [{ type: 'text', text: `Handled: ${JSON.stringify(message.parts)}` }],
}),
},
});
const app = express();
app.use(express.json());
app.post('/a2a', async (req, res) => {
const response = await server.handleRequest(req.body);
res.json(response);
});
app.get('/.well-known/agent.json', (_req, res) => {
res.json(server.getAgentCard());
});
app.listen(8000);
A2ATaskDelegator
A2ATaskDelegator handles routing, waiting, retries, optional direct fallback, and cancellation.
import { SekuireSDK } from '@sekuire/sdk';
const sdk = SekuireSDK.fromEnv();
await sdk.start();
const delegator = sdk.createDelegator({
timeout: 60_000,
pollInterval: 1_000,
maxRetries: 2,
retryDelayMs: 1_000,
retryBackoffMultiplier: 2,
});
const result = await delegator.delegate({
skill: 'github:issues',
message: 'Create an issue for login timeout regressions',
traceId: 'trace-123',
// Optional direct fallback target if routed mode fails
targetUrl: 'https://github-agent.example.com/a2a',
targetAgentId: 'agent_github',
});
console.log(result.status, result.taskId);
If you construct A2ATaskDelegator directly, setRuntimeToken(...) is still supported for compatibility.
Streaming delegation
for await (const event of delegator.delegateWithStreaming({
skill: 'document:summarize',
message: 'Summarize the release notes.',
})) {
console.log(event.status, event.message?.parts?.[0]);
}
Cancel delegation
delegator.cancelDelegation('task_id_here');
// or
// delegator.cancelAllDelegations();
Platform /a2a/tasks Compatibility
When using platform routing (/a2a/route), your target agent should expose:
POST /a2a/tasks(required for forwarded task execution)GET /.well-known/agent.json(recommended for discovery metadata)
Typical forwarded payload:
{
"task_id": "uuid",
"type": "summarize",
"input": {
"skill": "summarize",
"message": {
"role": "user",
"parts": [{ "type": "text", "text": "Summarize this text" }]
}
},
"context": {
"workspace_id": "ws_123",
"requester_id": "agent_router"
}
}
Return shape (success):
{
"task_id": "uuid",
"status": "completed",
"result": { "message": "..." },
"output": { "message": "..." }
}
Also ensure your manifest advertises matching capabilities:
capabilities:
provides:
- "summarize"
- "chat"
a2a:
upstream_url: "https://your-agent.example.com/a2a/tasks"