> ## 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.

# Your first agent

# Write Your Agent

Build an agent from scratch with full control over every capability.

<Info title="Prefer no code?">
  [Forge](forge) generates agent code from an API spec, TypeScript source, or plain English — in seconds.
</Info>

## Quick Start

A minimal working agent:

```typescript theme={null}
import { Agent } from '@svantic/sdk';

const agent = new Agent({
  name: 'ticket-agent',
  description: 'Manages support tickets — lookup, creation, and status updates.',
  port: 4000,
  mesh: {
    client_id: process.env.SAVANT_CLIENT_ID!,
    client_secret: process.env.SAVANT_CLIENT_SECRET!,
  },
});

agent.define_capability({
  name: 'get_ticket',
  description: 'Look up a support ticket by its ID.',
  parameters: {
    type: 'object',
    properties: {
      ticket_id: { type: 'number', description: 'The ticket ID' },
    },
    required: ['ticket_id'],
  },
  handler: async (args) => {
    const ticket = await db.find(args.ticket_id);
    return { id: ticket.id, subject: ticket.subject, status: ticket.status };
  },
});

await agent.start();
```

## Agent Configuration

<ParamField body="name" type="string" required>
  Agent identity in the mesh. Other agents and the dashboard see this name.
</ParamField>

<ParamField body="description" type="string" required>
  What this agent does. The mesh LLM reads this to decide when to route tasks to your agent. Be specific.
</ParamField>

<ParamField body="port" type="number">
  Port for the HTTP server. The mesh calls your agent at this port to invoke capabilities.
</ParamField>

<ParamField body="url" type="string">
  Full URL if you're not using port (e.g., behind a reverse proxy).
</ParamField>

<ParamField body="mesh" type="object">
  Credentials for mesh connection. Without this, the agent runs standalone (useful for testing).

  <Expandable title="properties">
    <ParamField body="client_id" type="string">
      From the Svantic dashboard.
    </ParamField>

    <ParamField body="client_secret" type="string">
      From the Svantic dashboard.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="version" type="string" default="1.0.0">
  Agent version shown in the dashboard.
</ParamField>

<ParamField body="instructions" type="string">
  System prompt for Smart Agents. Makes the agent reason about which capabilities to call.
</ParamField>

<ParamField body="llm" type="object">
  LLM configuration for Smart Agents.

  <Expandable title="properties">
    <ParamField body="provider" type="string">
      Allowed values: `gemini`, `openai`, `anthropic`.
    </ParamField>

    <ParamField body="model" type="string">
      Model name (e.g., gemini-2.0-flash, gpt-4o, claude-sonnet-4-20250514).
    </ParamField>
  </Expandable>
</ParamField>

## Capabilities

A capability is a single thing your agent can do.

<ParamField body="name" type="string" required>
  Capability name in snake\_case. The mesh calls this by name.
</ParamField>

<ParamField body="description" type="string" required>
  What this capability does. The LLM reads this to decide when to use it. Be specific about inputs and outputs.
</ParamField>

<ParamField body="parameters" type="object" required>
  JSON Schema defining the inputs. The LLM constructs arguments from natural language based on this schema.

  <Expandable title="properties">
    <ParamField body="type" type="string">
      Must be `"object"`.
    </ParamField>

    <ParamField body="properties" type="object">
      Parameter definitions. Each key is a parameter name with type, description, enum, default, etc.
    </ParamField>

    <ParamField body="required" type="array">
      List of required parameter names.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="handler" type="function" required>
  Async function (args, context) => result. Executes the capability and returns a result or throws an error.
</ParamField>

```typescript theme={null}
agent.define_capability({
  name: 'create_ticket',
  description: 'Create a new support ticket. Returns the ticket ID.',
  parameters: {
    type: 'object',
    properties: {
      subject: { type: 'string', description: 'Ticket subject line' },
      body: { type: 'string', description: 'Ticket description' },
      priority: { type: 'string', enum: ['low', 'normal', 'high', 'urgent'] },
    },
    required: ['subject', 'body'],
  },
  handler: async (args) => {
    const ticket = await db.create(args);
    return { id: ticket.id, status: 'created' };
  },
});
```

## Starting and Stopping

```typescript theme={null}
await agent.start();

process.on('SIGTERM', () => agent.stop());
```

`start()` creates an HTTP server, mounts A2A endpoints, and connects to the mesh.

## Tool Agent vs Smart Agent

By default, your agent is a **Tool Agent** — the mesh decides which capability to call. Add `instructions` and `llm` to make it a **Smart Agent** that reasons on its own:

```typescript theme={null}
const agent = new Agent({
  name: 'support-agent',
  description: 'Handles customer support end-to-end.',
  port: 4000,
  instructions: `You are a support specialist. When asked about a ticket:
    1. Look it up first
    2. Check the knowledge base for similar issues
    3. Draft a helpful response`,
  llm: {
    provider: 'gemini',
    model: 'gemini-2.0-flash',
  },
  mesh: { /* ... */ },
});
```

|                  | Tool Agent                        | Smart Agent                   |
| ---------------- | --------------------------------- | ----------------------------- |
| **LLM location** | Mesh only                         | Mesh + Agent                  |
| **Receives**     | Structured capability calls       | Natural language tasks        |
| **Decides**      | Nothing — executes what it's told | Which capabilities to call    |
| **Best for**     | Integrations, lookups, CRUD       | Complex reasoning, multi-step |

## What's Next

* [Connecting Agents](connecting-agents) — Discover and call other agents
* [Telemetry](telemetry) — Traces, spans, and observability
* [Embed in Existing Service](existing-services) — Add capabilities to an Express app
