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.
Composing Agents
You have tool specs from multiple sources — an OpenAPI spec for Zendesk, a natural-language-generated Datadog set — and you want to combine them into a single deployable agent. The compose step merges tool specs and generates everything needed to run.
Prerequisites
- One or more Tool Spec YAML files (generated by any Forge path)
- The Svantic CLI installed (
npm install -g @svantic/cli)
Standalone Mode: Full Project Generation
Generate a complete, self-contained agent project:
svantic forge agent --name support-bot \
--tools zendesk.tool-spec.yaml,slack.tool-spec.yaml,datadog.tool-spec.yaml \
--standalone
This creates a support-bot/ directory with:
| File | Purpose |
|---|
server.ts | Express server with all capabilities attached and triggers wired |
.env.template | All required environment variables collected from every tool spec |
package.json | Dependencies (@svantic/sdk, express, etc.) with a start script |
tsconfig.json | TypeScript configuration |
Dockerfile | Multi-stage build for production deployment |
capabilities/ | One .ts file per domain (zendesk, slack, datadog) |
triggers/ | Trigger handlers (webhooks, schedules) if any tool spec defines them |
The generated server
import { Agent } from '@svantic/sdk';
import { MeshConnector } from '@svantic/sdk/mesh';
import { attach } from '@svantic/sdk/forge';
import { zendesk_tools } from './capabilities/zendesk';
import { slack_tools } from './capabilities/slack';
import { datadog_tools } from './capabilities/datadog';
const agent = new Agent({
name: 'support-bot',
description: 'Manages Zendesk tickets, Slack messages, and Datadog incidents.',
});
attach(agent, [
...zendesk_tools,
...slack_tools,
...datadog_tools,
]);
const mesh = new MeshConnector(agent, {
svantic_url: process.env.SVANTIC_URL ?? 'https://api.svantic.com',
client_id: process.env.SVANTIC_CLIENT_ID!,
client_secret: process.env.SVANTIC_CLIENT_SECRET!,
});
await mesh.connect();
console.log('support-bot ready');
The attach() function registers all capabilities on the agent. MeshConnector dials the Svantic edge — one URL, no ingress needed. The agent runs in connected mode by default.
Run it
cd support-bot
cp .env.template .env # fill in your API keys
npm install
npm start
Embedded Mode: Capabilities Only
Omit --standalone to generate just the capability and trigger files, without the server scaffold:
svantic forge agent --name support-bot \
--tools zendesk.tool-spec.yaml,slack.tool-spec.yaml \
--out ./src/generated/
This writes capabilities and triggers into ./src/generated/ so you can import them into an existing agent:
import { Agent } from '@svantic/sdk';
import { attach } from '@svantic/sdk/forge';
import { zendesk_tools } from './src/generated/zendesk';
import { slack_tools } from './src/generated/slack';
const agent = new Agent({
name: 'my-existing-agent',
description: 'Already running agent with new Forge-generated tools.',
});
attach(agent, [...zendesk_tools, ...slack_tools]);
Programmatic Usage
import { compose, write_composed_agent } from '@svantic/sdk/forge';
const composed = await compose({
name: 'support-bot',
tool_specs: [
'./tools/zendesk.tool-spec.yaml',
'./tools/slack.tool-spec.yaml',
'./tools/datadog.tool-spec.yaml',
],
});
console.log(composed.tools); // Merged array of all tools
console.log(composed.env_vars); // Collected env vars from all specs
console.log(composed.triggers); // Merged triggers
// Write standalone project
await write_composed_agent(composed, {
output_dir: './support-bot/',
standalone: true,
});
// Or write embedded capabilities only
await write_composed_agent(composed, {
output_dir: './src/generated/',
standalone: false,
});
Collision Detection
When composing tools from multiple domains, Forge checks for duplicate tool names. If two specs define a tool with the same name, the CLI reports an error:
Error: Tool name collision detected:
"create_ticket" exists in both zendesk.tool-spec.yaml and jira.tool-spec.yaml
Options:
--prefix <domain> Prefix tool names with domain (e.g. zendesk_create_ticket)
--rename <old>=<new> Rename a specific tool
Resolving collisions
Option 1: Auto-prefix by domain
svantic forge agent --name support-bot \
--tools zendesk.tool-spec.yaml,jira.tool-spec.yaml \
--prefix domain \
--standalone
This produces zendesk_create_ticket and jira_create_ticket.
Option 2: Rename specific tools
svantic forge agent --name support-bot \
--tools zendesk.tool-spec.yaml,jira.tool-spec.yaml \
--rename jira:create_ticket=create_jira_ticket \
--standalone
Option 3: Edit the Tool Spec YAML
Open one of the .tool-spec.yaml files and change the tool name directly, then re-run compose.
Adding a Description
Forge auto-generates an agent description from the combined tool set. Override it:
svantic forge agent --name support-bot \
--tools zendesk.tool-spec.yaml,slack.tool-spec.yaml \
--description "Handles customer support tickets and notifies the team via Slack" \
--standalone
The .env.template
Forge collects every env field from every tool spec’s auth section and every trigger’s configuration, then writes a single .env.template:
# Auth — zendesk
ZENDESK_API_TOKEN=
ZENDESK_BASE_URL=https://your-domain.zendesk.com
# Auth — slack
SLACK_BOT_TOKEN=
# Auth — datadog
DATADOG_API_KEY=
DATADOG_APP_KEY=
# Svantic platform
SVANTIC_URL=https://api.svantic.com
SVANTIC_CLIENT_ID=
SVANTIC_CLIENT_SECRET=
Composing with Mixed Sources
You can compose tool specs generated from different paths in a single command. The YAML format is the same regardless of how it was produced:
svantic forge agent --name ops-bot \
--tools \
tools/zendesk.tool-spec.yaml,\
tools/billing.tool-spec.yaml,\
tools/datadog.tool-spec.yaml \
--standalone