Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.svantic.com/llms.txt

Use this file to discover all available pages before exploring further.

Connecting Agents

Your agent does not work alone. This guide covers how to discover other agents, call their capabilities, and integrate MCP tool servers so your runtime can reach peers and external tools through one mental model.

Discovering Agents

AgentDiscovery fetches and caches A2A agent cards from each peer’s /.well-known/agent-card.json endpoint. Use it to inspect names, skills, and metadata before you open a live connection.
import { AgentDiscovery } from '@svantic/sdk';

const discovery = new AgentDiscovery();
const card = await discovery.discover('http://billing-agent:4000');
console.log(card.name, card.skills);
Notes
  • Cards are cached for 60 seconds by default. Pass a different TTL in milliseconds (for example new AgentDiscovery(30_000) for 30s), or 0 to disable caching.
  • Batch: discover_all([url1, url2]) resolves many agents in parallel; failed URLs are skipped and only successful cards are returned.
  • Force refresh: discover(url, true) bypasses the cache for that URL once.
  • Manual invalidation: invalidate(url) or invalidate_all() when you know a peer redeployed.
RemoteAgent.connect() always fetches a fresh agent card for the connection itself; discovery caching is only for your own lookups.

Calling Remote Agents

RemoteAgent sends tasks to any A2A agent: natural-language messages, streaming responses, or structured capability calls.
import { RemoteAgent } from '@svantic/sdk';

const billing = await RemoteAgent.connect('http://billing-agent:4000');

// Natural language
const reply = await billing.send('What is customer acme-123 billed this month?');

// Structured invocation
const result = await billing.invoke_capability('get_invoice', {
  customer_id: 'acme-123',
  month: '2026-04',
});
Notes
  • Auth: RemoteAgent.connect(url, jwt) adds Authorization: Bearer <jwt> on requests when the peer requires it.
  • Streaming: for await (const event of billing.send_stream('...')) { ... } yields A2A stream events (messages, tasks, status and artifact updates).
  • Session forwarding: pass { session_id, tenant_id } as the third argument to invoke_capability when the remote agent should run in an existing session context.
  • Advanced: send_stream_message accepts a full A2A Message (see MessageBuilder).
Trace context propagates across RemoteAgent calls via W3C traceparent when telemetry is enabled (see Telemetry & tracing).

MCP Integration

Register MCP tool servers as agent capabilities so the mesh and other agents can invoke them like any other skill. The SDK spawns the server as a child process, runs the MCP handshake, and maps each tool to a capability.
await agent.register_mcp('chrome-devtools', {
  command: 'npx',
  args: ['chrome-devtools-mcp@latest'],
});
Notes
  • Call register_mcp before expose() or start() so discovered tools appear on the agent card.
  • Each MCP tool becomes a capability named {prefix}_{tool_name}. By default, prefix is the server name with hyphens replaced by underscores (for example chrome-devtoolschrome_devtools_navigate).
  • Custom prefix: third argument { tool_prefix: 'browser' }browser_<tool>.
  • Environment: { command: '...', args: [...], env: { API_KEY: '...' } } is merged with process.env for the child.
  • Cleanup: agent.close() or agent.stop() tears down MCP child processes.
For more patterns (filesystem, GitHub, ordering with define_capability), see MCP integration.

Full example: coordinator agent

A short coordinator discovers two peers, checks their cards, then invokes structured capabilities and returns a combined payload.
import express from 'express';
import { Agent, AgentDiscovery, RemoteAgent } from '@svantic/sdk';

const BILLING = 'http://billing-agent:4000';
const SUPPORT = 'http://support-agent:4001';

const app = express();
app.use(express.json());

const discovery = new AgentDiscovery(30_000);

const agent = new Agent({
  name: 'coordinator',
  description: 'Orchestrates billing and support agents.',
  public_url: 'https://coordinator.example.com',
});

agent.define_capability({
  name: 'customer_snapshot',
  description: 'Latest invoice plus open tickets for a customer.',
  parameters: {
    type: 'object',
    properties: {
      customer_id: { type: 'string' },
    },
    required: ['customer_id'],
  },
  handler: async (args) => {
    const cards = await discovery.discover_all([BILLING, SUPPORT]);
    if (cards.length < 2) {
      throw new Error('One or more peer agents are unreachable');
    }

    const billing = await RemoteAgent.connect(BILLING);
    const support = await RemoteAgent.connect(SUPPORT);

    const invoice = await billing.invoke_capability('get_invoice', {
      customer_id: args.customer_id,
      month: '2026-04',
    });

    const tickets = await support.invoke_capability('list_open_tickets', {
      customer_id: args.customer_id,
    });

    return { invoice, tickets };
  },
});

agent.expose(app);
app.listen(5000, () => console.log('Coordinator ready on :5000'));

See also