Agents
Define, execute, and manage AI agents with composable tool access
Agents
Agents are first-class AI primitives defined as markdown documents with YAML frontmatter. They encapsulate instructions, tool access, and composition rules into reusable, versioned specs that can be executed on demand or delegated to by other agents.
Concept
An agent combines:
- Instructions — Natural language directives (markdown body)
- Configuration — Model, tools, and permissions (YAML frontmatter)
- Composition — Which other agents it can delegate to
Examples:
| Agent | Mode | Tools | Use Case |
|---|---|---|---|
data-analyst | primary | generate_query, explain_schema, create_flashboard | Interactive data analysis |
sql-expert | subagent | generate_query, explain_schema | SQL query specialist |
research-bot | primary | web_search, fetch_page, call_agent | Web research with delegation |
AgentSpec Format
Agent specs are markdown documents with YAML frontmatter. The frontmatter configures the agent's behavior; the body provides natural language instructions.
---
name: Data Analyst
slug: data-analyst
mode: primary
model: orchestrator
tools:
- generate_query
- explain_schema
- create_flashboard
sub_agents:
- sql-expert
permissions:
max_cost_per_run: 5.00
---
# Goal
You are a data analyst specializing in e-commerce metrics.
Analyze connected data sources and build visual dashboards.
## Guidelines
- Always explain your reasoning before running queries
- Use gold-layer tables when available for performance
- Create flashboards for multi-metric analysesFrontmatter Fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name |
slug | string | Yes | URL-safe identifier, unique per org |
mode | "primary" | "subagent" | Yes | Whether agent appears in picker or only as delegate target |
model | string | No | Model override (default: org setting) |
tools | string[] | Yes | Allowed tool slugs (see Tool Access) |
sub_agents | string[] | No | Agent slugs this agent can delegate to via call_agent |
permissions | object | No | Fine-grained permission overrides |
description | string | No | Short description shown in agent picker |
Permissions
| Field | Type | Description |
|---|---|---|
allowed_connections | string[] | Restrict which connections the agent can access |
allowed_actions | string[] | Restrict which action kinds are permitted |
max_cost_per_run | number | Maximum cost budget per execution |
Agent Modes
Agents operate in one of two modes:
| Mode | Appears in Picker | Can Use call_agent | Can Be Called | Use Case |
|---|---|---|---|---|
primary | Yes | Yes | Yes | User-facing entry points |
subagent | No | No | Yes | Domain specialists called by primary agents |
Subagents cannot use call_agent. This prevents infinite delegation loops. Only primary agents can delegate.
Agent Run Lifecycle
Each execution creates an AgentRun that tracks status through a defined lifecycle:
| Status | Description | Can Transition To |
|---|---|---|
PENDING | Created, awaiting execution | RUNNING, CANCELLED |
RUNNING | Actively executing tools | AWAITING_APPROVAL, COMPLETED, FAILED, CANCELLED |
AWAITING_APPROVAL | Write tool needs human approval | RUNNING (approved), CANCELLED (rejected) |
COMPLETED | Finished successfully | — (terminal) |
FAILED | Encountered an error | — (terminal) |
CANCELLED | Manually cancelled or rejected | — (terminal) |
Execution Model
Agent execution uses Server-Sent Events (SSE) for real-time streaming. Each tool invocation is tracked as a step, and write operations create approval gates.
SSE Event Types
| Event | Description |
|---|---|
run_started | Execution began |
step_started | Tool invocation starting |
step_completed | Tool invocation finished |
approval_required | Write tool needs human approval |
narration | Agent's reasoning/commentary |
run_completed | Execution finished successfully |
run_failed | Execution encountered an error |
DAG Building
During execution, every tool call is recorded as a step in a directed acyclic graph (DAG). This DAG captures the execution order and dependencies, enabling crystallization — converting the run into a deterministic automation.
Tool Access
Agents can use any combination of the following tools. Grant only what's needed for the agent's domain.
| Tool | Category | Risk | Description |
|---|---|---|---|
generate_query | Data | Read | Generate and execute SQL queries against connected schemas |
explain_schema | Data | Read | Explain table structures and column meanings |
web_search | Research | Read | Search the web via Tavily API |
fetch_page | Research | Read | Extract readable content from URLs |
call_agent | Delegation | Read | Invoke another agent by slug |
create_flashboard | Output | Write | Build a persistent dashboard from data |
http_request | Integration | Write | Make arbitrary HTTP requests to external APIs |
Tool Risk Levels
Read tools execute without approval. Write tools create an approval gate, pausing execution until a human approves or rejects.
Composition and Delegation
The call_agent tool enables agents to delegate tasks to other agents by slug. This is the core composition primitive.
How It Works
- Primary agent encounters a task outside its expertise
- Calls
call_agent(agent="sql-expert", question="Optimize this query...") - Subagent executes with its own tools and instructions
- Result is returned to the calling agent
- Calling agent continues with the subagent's response
Rules
| Rule | Description |
|---|---|
| Explicit sub_agents | An agent can only call agents listed in its sub_agents field |
| Depth guard | Maximum delegation depth prevents infinite recursion |
| No self-calls | An agent cannot call itself |
| Subagent restriction | Subagents cannot use call_agent — only primary agents can delegate |
Composition Example
# Primary agent: operations-bot
sub_agents:
- data-analyst
- report-builder
# When operations-bot needs data analysis, it calls:
# call_agent(agent="data-analyst", question="...")
# The data-analyst runs with its own tools, returns resultsPerformance and Evaluation
Agent specs track execution statistics:
| Metric | Description |
|---|---|
| Total runs | Number of times the agent has been executed |
| Success rate | Percentage of runs that completed successfully |
| Average duration | Mean execution time across runs |
| Crystallization count | How many runs have been crystallized into automations |
| Feedback stats | Thumbs up/down from users |
Access stats via GET /api/v1/agents/specs/{spec_id}/stats.
Creating Agent Specs
curl -X POST https://vai-dev.virtuousai.com/api/v1/agents/specs \
-H "Authorization: Bearer $VAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"markdown": "---\nname: Data Analyst\nslug: data-analyst\nmode: primary\ntools:\n - generate_query\n - explain_schema\n---\n\n# Goal\n\nAnalyze connected data sources and answer questions about business metrics."
}'The API accepts the full agent spec as a markdown string. The YAML frontmatter is parsed for configuration, and the markdown body becomes the agent's instructions.
---
name: Data Analyst
slug: data-analyst
mode: primary
tools:
- generate_query
- explain_schema
---
# Goal
Analyze connected data sources and answer questions
about business metrics.Crystallization
Successful agent runs can be crystallized into deterministic automations. The DAG built during execution is extracted and converted into an automation workflow that can be replayed without AI involvement.
curl -X POST https://vai-dev.virtuousai.com/api/v1/agents/runs/{run_id}/crystallize \
-H "Authorization: Bearer $VAI_API_KEY"See Crystallization for details.
Best Practices
- Keep instructions focused — One agent, one domain. A data analyst should not also handle email campaigns
- Use subagent mode for specialists — If an agent is only called by other agents, make it a subagent
- Grant minimum necessary tools — Don't give
http_requestto an agent that only needsgenerate_query - List sub_agents explicitly — Avoid open-ended delegation; enumerate which agents can be called
- Test with approval flow — Review tool calls before enabling autonomous execution
- Write clear instructions — The markdown body is the agent's primary guidance; be specific about behavior
OpenAPI Reference
For detailed endpoint schemas, request/response formats, and authentication: