Building agents¶
An agent is an AI worker your module ships: an LLM with a system prompt, a set of tools it may call, and a place in a hierarchy of other agents. You declare an agent the same way you declare a model — as a small, declarative Python class. Victor reads the class, registers the agent when your module installs, and renders it as an editable record in the app.
This page covers how to declare an agent, the full set of spec fields, how to compose agents into a hierarchy, and how agents behave as in-app records that operators can tune without touching code.
Declare an agent¶
Subclass victor.agents.Agent and set class attributes. This is a declarative spec — you set
fields, you do not write runtime code. Give the agent a unique name, a model, an instructions
prompt, and the tools it is allowed to call.
from victor import agents
class Researcher(agents.Agent):
name = "researcher" # unique key; used in the run URL
label = "Researcher" # human-readable label
model = "google:gemini-3-flash-preview" # "provider:model-id"
description = "Searches company contacts and reports what it finds."
instructions = "You research the company's contacts. Use search_contacts and report concisely."
tools = ["search_contacts"] # names of tools this agent may call
A few things to note:
nameis the agent's identity everywhere — it is how other agents reference it and it appears in the agent's run URL. Keep it unique and stable.modelis a"provider:model-id"string, e.g.anthropic:claude-sonnet-4-6orgoogle:gemini-3-flash-preview. The exact providers and models available depend on your instance.toolslists the names of registered tools the agent may call. The tool code is wired into the module viamodule.yaml(see Register agents).
Tip
Write instructions like a job description: what the agent is for, which tools to reach for, and
how to respond. The model follows this prompt on every run.
Spec fields¶
Every field is optional except name. Set only the ones you need; the rest fall back to the defaults
below.
from victor import agents
class MyAgent(agents.Agent):
name = "my_agent" # unique key
label = "My Agent" # display label
model = "anthropic:claude-sonnet-4-6" # "provider:model-id"
reasoning = "off" # thinking level: "off" | "low" | "medium" | "high"
instructions = "" # system prompt
description = "" # what this agent does — read by a parent to decide when to delegate
tools = [] # names of registered tools it may call
skills = [] # names of SKILL.md capability files it may read
subagents = [] # agent names nested as sub-agents (delegation)
capabilities = [] # agent names it may call laterally as peers
directcontact = False # True = entry point for end-user conversations
all_tools = False # True = also auto-gain every module's read-only tools
| Field | Type | Default | Purpose |
|---|---|---|---|
name |
str |
required | Unique agent key. Identifies the agent everywhere and appears in its run URL. |
label |
str |
— | Human-readable label shown in the app. |
model |
str |
— | The LLM, as a "provider:model-id" string. |
reasoning |
str |
"off" |
Thinking level: "off", "low", "medium", or "high". In-app this field is labelled Thinking level. "off" disables provider thinking; higher values raise the thinking budget. |
instructions |
str |
— | The system prompt / instructions for the agent. |
description |
str |
— | Short statement of what the agent does. A parent agent reads this to decide when and how to delegate to it. |
tools |
list[str] |
[] |
Names of registered tools the agent may call. |
skills |
list[str] |
[] |
Names of SKILL.md capability files the agent may read on demand. |
subagents |
list[str] |
[] |
Agent names nested as sub-agents (delegation). |
capabilities |
list[str] |
[] |
Agent names the agent may call laterally as peers. |
directcontact |
bool |
False |
When True, marks this agent as the entry point for end-user conversations. |
all_tools |
bool |
False |
When True, the agent auto-gains every installed module's read-only tools on top of its declared tools, resolved per run. |
Thinking level¶
reasoning controls how much the model deliberates before answering. "off" is the default and
turns provider thinking off; "low", "medium", and "high" raise the thinking budget. Use a
higher level for agents that plan multi-step work or reason over complex data, and leave it "off"
for fast, straightforward responders.
Tools vs. skills¶
Both extend what an agent can do, but they are different in kind:
toolsare actions the agent can take — registered functions it may call (read records, send an email, and so on). See Tools.skillsareSKILL.mdfiles — instructions and knowledge the agent reads on demand, not executable code. Use a skill to teach the agent a procedure or give it reference material. See Skills.
from victor import agents
class Skillhost(agents.Agent):
name = "skillhost"
label = "Skillhost"
model = "anthropic:claude-sonnet-4-6"
instructions = "You greet users using the greeter skill."
skills = ["greeter"] # names of SKILL.md files this agent may read
all_tools¶
Setting all_tools = True grants the agent every installed module's read-only tools in addition
to whatever it lists in tools, resolved fresh on each run. This is handy for a general-purpose
front-door agent that should be able to read across the whole instance without you enumerating every
tool by hand. Mutating and approval-gated tools are never auto-granted this way — list those
explicitly in tools.
Register agents in module.yaml¶
Declaring an Agent class is not enough on its own — Victor needs to know which Python submodules to
load. List them under the agents: key in your module.yaml, as dotted import paths
relative to your module package. If your agents call custom tools, list the tool submodules under
tools: as well.
name: assistant
label: Assistant
version: 0.1.0
requires: [contact, mail] # dependencies installed first
agents: [agents.researcher, agents.manager, agents.frontdesk]
tools: [tools.contacts] # tool modules an agent's `tools` list can reference
Here agents.frontdesk means the file agents/frontdesk.py inside your module package. Every
Agent subclass in a listed submodule is registered when the module installs.
Build an agent hierarchy¶
Agents compose. A single agent can hand work to others in two distinct ways, and the difference matters:
subagents— nested delegation. The parent hands a whole slice of multi-step work down to a specialist sub-agent and gets the result back. Use this to break a big job into focused workers.capabilities— lateral calls. The agent calls another agent as a peer service, the way you would call a shared function, rather than owning it as a child.
In both cases, the description field on the target agent is what a parent reads to decide
when and why to route to it. Write descriptions that clearly state what the agent is good for.
Subagents (nested delegation)¶
Each name in subagents must be another declared agent. The child's description tells the parent
when to hand off.
from victor import agents
class Helper(agents.Agent):
name = "helper"
label = "Helper"
model = "anthropic:claude-sonnet-4-6"
instructions = "You help."
description = "Helps with things" # parent reads this to decide when to delegate
class Boss(agents.Agent):
name = "boss"
label = "Boss"
model = "anthropic:claude-sonnet-4-6"
instructions = "Delegate to helper."
description = "The boss"
subagents = ["helper"] # nests helper as a sub-agent
Capabilities (lateral peers)¶
List peer agent names in capabilities. The caller may invoke them as services without nesting them
as children.
from victor import agents
class Target(agents.Agent):
name = "target"
label = "Target"
model = "anthropic:claude-sonnet-4-6"
instructions = "You are the target."
description = "Does the target work"
class Caller(agents.Agent):
name = "caller"
label = "Caller"
model = "anthropic:claude-sonnet-4-6"
instructions = "Use the target capability."
capabilities = ["target"] # may call `target` as a lateral peer
A complete example¶
This front-desk agent brings the pieces together: a thinking level, a capability it can delegate to,
the directcontact flag that makes it the conversation entry point, and all_tools so it can read
across every installed module on top of its declared tool list.
from victor import agents
class Frontdesk(agents.Agent):
name = "frontdesk"
label = "Front Desk"
model = "google:gemini-3-flash-preview"
reasoning = "medium" # thinking level
description = "Greets users and answers questions about the company's data."
instructions = "You are the front desk assistant. ..."
tools = ["read_records", "create_record", "update_record", "send_email"]
capabilities = ["researcher"] # may delegate research laterally
directcontact = True # entry point for end-user conversations
all_tools = True # also auto-gain every module's read-only tools
directcontact is the front door
Mark exactly the agent(s) meant to talk to end users with directcontact = True. That flag makes
the agent an entry point for conversations; specialist sub-agents and capabilities usually leave
it False and are reached only through a front-door agent.
Agents are editable in-app records¶
Every agent you declare is also a record under Settings → Agents. This lets an operator tune an agent's behaviour without a code change:
- Module-defined (code) agents are seeded as read-only records — the class is the source of truth.
- Agents created in the UI are fully editable records.
The in-app form exposes an agent's Model, Thinking level, Prompt (instructions), Tools, Skills, and its Subagents / Capabilities. Edits take effect on the agent's next run — there is nothing to redeploy.
Instance-wide overrides¶
Two System Parameters let an operator override every agent at once, which is useful for switching the whole instance to a cheaper or faster model during testing:
| System Parameter | Effect |
|---|---|
agent.model |
Forces every agent's model (e.g. google:gemini-2.5-flash). Leave unset to fall back to each agent's own model. |
agent.reasoning |
Forces every agent's thinking level (off / low / medium / high). Leave unset to fall back to each agent's own reasoning. |
When set, these win over the per-agent values; when unset, each agent uses what it declares.
Next steps¶
- Give your agent something to act on — declare Models & fields.
- Give it actions — write Tools.
- Teach it a procedure — author a Skill.
- Wire it up — see Modules &
module.yaml.