Agents & Sub-Agents
Bahulam runs one primary coding agent that owns the final answer and the actual project outcome. For larger tasks, that agent can delegate focused work to built-in or user-defined sub-agents.
Sub-agents are not separate chat sessions. They are bounded workers inside the same execution path. Each one gets a specific task, a limited tool set, and a handoff contract. The primary agent reads the handoff, decides what to trust, and continues the main turn.
Sub-Agent Spawning as an Industry Pattern
Sub-agent spawning is an emerging architectural pattern adopted by every major coding agent in the ecosystem. The concept is simple: when a primary agent receives a complex request, it decomposes it into bounded subtasks and delegates each to a focused worker — a sub-agent — that runs with its own system prompt, tool restrictions, and iteration budget.
Why this pattern emerged:
- Context window limits — A single agent can only hold so much information. Isolating work in sub-agents prevents context pollution.
- Specialization — Different tasks need different expertise. A code-review sub-agent uses a different system prompt than a debugging one.
- Parallelism — Independent subtasks can run concurrently, reducing wall-clock time.
- Accountability — Each sub-agent returns a handoff with evidence. The primary agent evaluates, accepts, or re-delegates.
How it shows up across tools:
| Tool / Project | Approach |
|---|---|
| Bahulam | Primary agent delegates to built-in roles (explore, plan, verify, debug, refactor) or user-defined agents. Sub-agents receive a task prompt, restricted tools, and an iteration limit; they return a handoff with evidence. |
| Claude Code | Orchestrator spawns sub-agents via AgentTool; supports recursive nesting and parallel execution. Sub-agents can spawn sub-agents. |
| OpenAI Codex CLI | Spawns specialized agents in parallel, aggregates results. Sub-agents inherit the orchestrator’s model. |
| Cline | Coordinator breaks work into subtasks, delegates to specialist sub-agents with isolated tools and context. Sequential approval gates. |
| GitHub Copilot | Sub-task delegation with explicit concurrency and depth limits to prevent runaway recursion. Lifecycle events streamed back to the main agent. |
| Aider | Lead agent delegates to developer agents, results reviewed by a QA sub-agent before final output. |
| Hermes | Brain/planning agent delegates coding tasks to OpenCode CLI sub-agents for implementation. |
| Oh-My-OpenCode (OMO) | 11 specialized agents managed by the Sisyphus orchestration system, running in parallel. |
| Windsurf | Cascade agent delegates to specialized sub-agents for multi-step workflows. |
Common architecture across all implementations:
- Parent agent receives a complex task
- Work is decomposed into bounded, parallelizable subtasks
- For each subtask, a sub-agent is spawned with:
- Isolated LLM context
- A specific system prompt
- A restricted tool set
- An iteration budget (max tool calls)
- Sub-agents run independently — sequentially or in parallel
- Results are collected and the parent synthesizes the final output
Guardrails are applied universally: depth limits (prevent infinite nesting), concurrency limits (control parallel cost), and output-only returns (sub-agents return results, not intermediate tool traces).
For a deeper dive with visual walkthroughs and ecosystem comparisons, see the companion article: Sub-Agent Spawning Pattern.
Built-In Agents
Bahulam exposes built-in delegation roles for common coding work:
| Role | Purpose | Typical Tools |
|---|---|---|
explore | Search and read the codebase before a change | search_code, read_file, get_project_overview |
plan | Design an implementation approach | read-only tools |
verify | Check claims, tests, or implementation details | read-only tools, shell when allowed |
debug | Investigate a failing command, stack trace, or regression | read/search tools, shell when allowed |
refactor | Work through a bounded refactor task | read/edit/test tools as policy allows |
advise | Get a second opinion on which peer to invoke or what to do next | lightweight classification |
These agents run with read-only access by default — they search, read, and analyze, but do not modify files unless explicitly configured otherwise. You invoke them with slash commands:
/explore how does the auth middleware work
/architect design the payment retry logic
/review security of the file upload endpointThe agent resolves the command, picks the right role, spawns a sub-agent with a focused prompt, and weaves the result back into the main turn.
Execution Model
Sub-agent execution has two parts: routing and tool execution.
Routing decides which agent should receive the task. Tool execution still runs through the primary CLI or workspace process, where approvals, sandboxing, plugin handlers, MCP clients, and trace events already live. The sub-agent does not bypass those controls. It receives only the tools declared for that agent, chooses from that scoped list, and the client executes those calls on its behalf.
Every tool a sub-agent uses still runs through the same approvals, sandbox, and policy as the primary agent — delegation never bypasses your controls.
This means a plugin tool such as docker_analyze should normally be used by
the docker-analyzer sub-agent when that agent is selected. The primary agent
may still call a plugin tool directly when the user explicitly asks for that
tool or when no sub-agent routing is required, but delegated work is attributed
to the sub-agent and constrained by its tool list.
There are two practical entry points:
- Autonomous delegation — the primary agent receives runnable agents in its context and asks the backend to spawn one when the task calls for it.
- Explicit run — the user invokes a specific agent directly:
/run docker-analyzer "Analyze all running Docker containers"Plugin agents are workspace-scoped by default. They are available in a plugin workspace and can be run explicitly by slug. For autonomous main-loop delegation, allowlist the plugin agent slug in plugin settings so it appears as a runnable delegation target.
User-Defined Agents
For tasks that don’t fit the built-in roles, you can define your own sub-agents. A user-defined agent is a plain-text file — YAML, JSON, or Markdown — that declares the agent’s identity, capabilities, tools, and system prompt.
Definition Formats
User-defined agents can be written in any of three formats. All are equivalent and parse into the same internal shape.
YAML (recommended):
apiVersion: agent.framework/v1
kind: SubAgent
metadata:
name: security-scanner
role: specialist
description: Scans for common security vulnerabilities
capabilities:
- security
- audit
agent:
model: claude-sonnet-4-6
max_iterations: 15
system_prompt: |
You are a security scanning agent. Review code for:
- SQL injection
- XSS vulnerabilities
- Hardcoded secrets
- Insecure deserialization
Report each finding with file:line references and severity.
tools:
- read_file
- search_code
- list_filesJSON:
{
"name": "security-scanner",
"description": "Scans for common security vulnerabilities",
"role": "specialist",
"model": "claude-sonnet-4-6",
"max_iterations": 15,
"prompt": "You are a security scanning agent. Review code for:\n- SQL injection\n- XSS vulnerabilities\n- Hardcoded secrets\n- Insecure deserialization\n\nReport each finding with file:line references and severity.",
"tools": ["read_file", "search_code", "list_files"],
"capabilities": ["security", "audit"]
}Markdown with YAML frontmatter:
---
name: security-scanner
description: Scans for common security vulnerabilities
role: specialist
model: claude-sonnet-4-6
max_iterations: 15
tools:
- read_file
- search_code
- list_files
capabilities:
- security
- audit
---
You are a security scanning agent. Review code for:
- SQL injection
- XSS vulnerabilities
- Hardcoded secrets
- Insecure deserialization
Report each finding with file:line references and severity.Place these files in one of the search paths below. File extensions determine
the format: .yaml / .yml, .json, or .md.
Where Agents Live
Bahulam searches for agent definitions in the following locations, in order of priority (project-level files shadow global ones):
| Location | Scope | Example |
|---|---|---|
.bahulam/agents/ | Project | myproject/.bahulam/agents/security-scanner.yaml |
~/.bahulam/agents/ | Global (all projects) | ~/.bahulam/agents/security-scanner.yaml |
Legacy path .kepler/agents/ is also checked for compatibility with older
projects.
If two agents have the same name, the project-local one wins.
Configuration Reference
| Field | Type | Default | Description |
|---|---|---|---|
name | string | required | Unique name for the agent |
description | string | ” | Short summary of what the agent does |
role | string | specialist | Role for framework matching (specialist, planner, reviewer, explorer, coder) |
model | string | null | Model override (e.g., claude-sonnet-4-6) |
tools | string[] | [] | Allowed tool names (canonical Bahulam tool names like read_file, search_code, shell) |
capabilities | string[] | [] | Routing hints for framework matching |
system_prompt | string | ” | Instructions that define the agent’s behavior |
max_iterations | number | 10 | Maximum tool-call rounds per delegation |
max_tokens | number | 4096 | Maximum output tokens per response |
can_delegate | boolean | false | Whether this sub-agent can itself spawn sub-agents |
can_be_delegated_to | boolean | true | Whether other agents can delegate work to this agent |
Agent Commands
# List local agents in the current workspace
/agents
# List backend-published agents
bahulam agent list
# Show full definition of a backend-published agent
bahulam agent get security-scanner
# Optional: publish local agent definitions to the backend
bahulam agent sync
# Sync from a custom directory
bahulam agent sync --dir ./team-agentsLocal delegation does not require sync. The CLI and workspace read
.bahulam/agents/ directly from the active project root and include those
definitions in the current delegation context.
The sync command is optional publishing. It scans your local
.bahulam/agents/ directory, reads every definition file, and pushes them to
the backend for account/cloud reuse. Syncs are idempotent — repeatedly syncing
the same definitions is harmless.
How Delegation Works
When the primary agent needs to delegate a task:
- It selects a runnable target agent slug and a task prompt
- The runtime spawns a sub-agent with the agent’s configured system prompt, tool list, and iteration budget
- The sub-agent works independently — searching files, reading code, running commands — within its allowed tool set
- Tool calls are brokered back through the primary CLI or workspace executor, so plugin tools, MCP tools, approvals, hooks, and sandbox policy all use the same local enforcement path
- When done, it returns a handoff containing evidence, findings, and any outputs
- The primary agent evaluates the handoff, decides what to incorporate, and continues the main turn
User-defined agents appear in the delegation target list alongside built-in roles. You can reference them by their slug (the filename without extension).
Creating Agents During a Session
The primary agent can also create new user-defined agents on the fly during a conversation. When it detects a recurring pattern that would benefit from a dedicated specialist, it can:
- Create a YAML file in
.bahulam/agents/<slug>.yamlusing the agent’s scaffold template - Sync it to the cloud so it’s available for future sessions
This makes the agent ecosystem self-extending: the primary agent architects its own tooling.
Delegation Flags
Two boolean fields control how an agent participates in the delegation graph:
can_delegate(defaultfalse) — Set totrueif this sub-agent should be able to spawn its own sub-agents. Useful for orchestrator-style agents that coordinate multiple specialists.can_be_delegated_to(defaulttrue) — Set tofalseto prevent the primary agent from delegating to this agent directly. Useful for agents that are only invoked as part of a workflow or by other agents.
These flags let you control delegation depth and prevent unexpected nesting.