Guides

Build an agent

Define an AI agent that understands your product model, plans typed actions, and runs through the same canonical surfaces as humans.

Vadyl agents are first-class citizens of the platform. They read through the access engine, write through the runtime bridge, plan in a typed IR (no raw shell, SQL, or filesystem), bill against project quotas, and expose themselves through MCP — all canonical, all observable, all under the same product model and governance envelope as your humans.

Define an agent

// src/agents/SupportAgent.ts
import { agent, llm } from "@vadyl/sdk";


export default agent.define("SupportAgent", {
  description: "Helps users resolve order issues",

  // Pick a model by capability requirement, not by hardcoded name
  model: llm.require({
    tier: "frontier",
    capabilities: ["tool-use", "long-context"],
  }),

  // Skills the agent may use (typed, capability-checked)
  skills: [
    agent.skill.entityRead("Order"),
    agent.skill.entityRead("Customer"),
    agent.skill.entityWrite("RefundRequest"),
    agent.skill.workflowStart("processRefund"),
    agent.skill.connection("email", { operations: ["send"] }),
  ],

  // Memory scope (immutable, supersedable, scoped to the user)
  memory: agent.memory.scopedTo("ctx.userId", { tier: "long-term" }),

  // Token budget per run
  budget: { maxTokens: 50_000, maxToolCalls: 30 },

  // The system instruction is part of the contract
  instruction: `
    You help customers resolve order issues. You can read orders and
    customers, create refund requests, start the refund workflow, and
    send emails. You cannot delete data or modify products.
  `,
});

Capability-aware model routing

Don't hardcode a model name. Declare the capabilities you need; Vadyl resolves through the project's LLM connection bindings. Switching from Claude to GPT-5 to a self-hosted model is a binding change — your agent definition stays the same.

Typed plan IR

Agents plan in a closed discriminated union of 60+ typed operation kinds. There is no ExecuteShellCommand, no ExecuteRawSql, no InvokeProviderSdkDirectly. Every plan operation composes existing Vadyl typed ASTs — entity ops, schema ops, branching ops, automation ops, model ops, memory ops, connection ops, workflow ops, sub-agent spawns, HITL prompts, control flow.

13-stage plan validation

Every plan is validated through a 13-stage pipeline before any step executes: structural checks, PCG references, capability declarations, access enforcement, DAG cycle detection, budget bounds, coherence, protection, schema compatibility, federation, quotas, signatures, and risk rollup. Risk rollup is the maximum of step risks (it cannot understate).

Memory model

Memory is immutable with supersession — facts are never hard-deleted (except by legal compliance retention sweepers). New facts can supersede older ones via SupersededByFactId. The memory store consults the same access engine as entity reads.

MCP exposure

Agents (and selected actions) can be exposed through MCP — the Model Context Protocol — for use by external IDEs, AI assistants, and other agents. Exposure is filtered by the project's capability grants:

// vadyl.config.ts
mcp: {
  enabled: true,
  expose: {
    agents: ["SupportAgent"],
    tools:  ["entityRead:Customer", "entityRead:Order"],
  },
},

Run an agent

// From a handler
const run = await ctx.agents.SupportAgent.run({
  prompt: "Refund order #12345 due to defective product",
  userId: ctx.actor.userId,
});

// Or from the CLI
vadyl agents run SupportAgent --prompt "Refund order #12345"

// Inspect the run
vadyl agents runs show <runId>      # full plan, steps, tokens, decisions
vadyl explain agent-run <runId>     # canonical reasoning trace