Skip to Content
A2A Public APISDK Reference

SDK Reference

Package: @cendriix/a2a — TypeScript SDK for the A2A Public API. Status: Pre-release. SDK repo (a2a-sdk-ts) created but not yet published.

A2AClient

import { A2AClient } from '@cendriix/a2a'; const client = new A2AClient(options);

Options

OptionTypeRequiredDefaultDescription
apiKeystringYesAccess Grant secret
baseUrlstringNo'https://api.cendriix.ai'API base URL
timeoutnumberNo30_000Request timeout in milliseconds
retriesnumberNo3Max automatic retries on transient errors
retryDelaynumberNo1_000Base delay between retries (exponential backoff)
dpopbooleanNotrueEnable DPoP proof generation
fetchtypeof fetchNoglobalThis.fetchCustom fetch implementation

handshake()

Validate the connection and API key.

const result = await client.handshake(); // { ok: true, tenantId, grantId, capabilities, agentIds, expiresAt, serverVersion }

invoke()

Invoke an agent synchronously. Waits for the task to reach a terminal state.

const task = await client.invoke(agentId, params, options?);

Params

FieldTypeRequiredDescription
messagestringYesThe task prompt or instruction
partsA2aPart[]NoStructured content parts (overrides message)
contextRecord<string, unknown>NoAdditional context passed as data part
sessionIdstringNoGroup messages in a conversation session
skillIdsstring[]NoRestrict to specific skills

Options

FieldTypeDefaultDescription
timeoutnumber300_000Max wait time for completion (ms)
idempotencyKeystringAuto-generated UUIDDeduplication key
signalAbortSignalAbort signal for cancellation

Example

const task = await client.invoke('code-reviewer', { message: 'Review PR #42 for security vulnerabilities', context: { repository: 'acme/payments', prNumber: 42 }, }); if (task.status === 'COMPLETED') { for (const artifact of task.artifacts) { console.log(`[${artifact.name}]`, artifact.parts[0]?.text); } }

stream()

Invoke an agent and stream events as an async iterator.

const stream = client.stream(agentId, params, options?); for await (const event of stream) { switch (event.type) { case 'status': console.log(event.event.status.state); break; case 'artifact': console.log(event.event.artifact.name); break; case 'message': console.log(event.message.parts[0]?.text); break; } }

Agent discovery

listAgents()

const agents = await client.listAgents(); // [{ id, slug, name, description, skills, visibility, inputModes, outputModes }]

getAgentCard()

const card = await client.getAgentCard('code-reviewer'); // { card: { name, description, capabilities, skills }, signature, signedAt, keyId }

getTask()

const task = await client.getTask(taskId);

listTasks()

const { tasks, nextPageToken } = await client.listTasks({ agentId: 'code-reviewer', status: 'COMPLETED', pageSize: 50, });

cancelTask()

await client.cancelTask(taskId);

Error types

ClassCodeWhen
AgentNotFoundError-32010Agent slug/ID does not exist
AgentDisabledError-32011Agent is disabled
UnauthorizedError-32012Token expired or invalid
ForbiddenError-32013Insufficient capabilities
QuotaExceededError-32014Rate limit or budget exceeded
CrossTenantRejectedError-32015Cross-tenant invocation without consent
TaskNotFoundError-32001Task ID does not exist
TaskNotCancelableError-32002Task in terminal state
import { A2AError, QuotaExceededError } from '@cendriix/a2a'; try { await client.invoke('orchestrator', { message: '...' }); } catch (err) { if (err instanceof QuotaExceededError) { console.log(`Rate limited. Retry after ${err.data?.retryAfter}s`); } }

React hooks

useA2A

import { useA2A } from '@cendriix/a2a/react'; function ReviewPanel({ prUrl }: { prUrl: string }) { const { invoke, task, isLoading, error } = useA2A({ apiKey: process.env.NEXT_PUBLIC_CENDRIIX_API_KEY!, }); return ( <div> <button onClick={() => invoke('code-reviewer', { message: `Review ${prUrl}` })} disabled={isLoading}> {isLoading ? 'Reviewing...' : 'Start Review'} </button> {error && <p>{error.message}</p>} {task?.status === 'COMPLETED' && ( <pre>{task.artifacts[0]?.parts[0]?.text}</pre> )} </div> ); }

useA2AStream

import { useA2AStream } from '@cendriix/a2a/react'; const { startStream, artifacts, status, isStreaming } = useA2AStream({ apiKey: process.env.NEXT_PUBLIC_CENDRIIX_API_KEY!, });

Vercel integration

Edge Runtime

// app/api/review/route.ts import { A2AClient } from '@cendriix/a2a'; export const runtime = 'edge'; export async function POST(request: Request) { const { prUrl } = await request.json(); const client = new A2AClient({ apiKey: process.env.CENDRIIX_API_KEY! }); const task = await client.invoke('code-reviewer', { message: `Review ${prUrl}`, context: { prUrl }, }); return Response.json({ status: task.status, review: task.artifacts[0]?.parts[0]?.text }); }

Server Actions

'use server'; import { A2AClient } from '@cendriix/a2a'; const client = new A2AClient({ apiKey: process.env.CENDRIIX_API_KEY! }); export async function analyzeCode(code: string) { const task = await client.invoke('code-reviewer', { message: 'Review this code for issues', parts: [{ text: code, mediaType: 'text/plain' }], }); return { status: task.status, findings: task.artifacts.map(a => ({ name: a.name, content: a.parts[0]?.text ?? '' })) }; }
Last updated on