Agents
Ash has a main orchestrator agent and optional subagents. Subagents run their own tool-and-LLM loop, then return results to the main conversation.
Agents In 30 Seconds
Use a subagent when work needs an isolated multi-step loop.
- Main agent: handles normal conversation and tool calls
- Subagent: runs delegated work with its own prompt, iteration budget, and tool scope
Current built-in subagents:
task- general multi-step workerplan- produces structured implementation plans
When To Use Agents Vs Skills
Use use_agent when you need autonomous execution across multiple iterations.
Use skills when you want reusable instructions in SKILL.md and workflow conventions.
- Agent: Python-defined behavior, isolated loop
- Skill: markdown-defined behavior, reusable instructions
See Skills for skill design and lifecycle.
Quick Start
Ask Ash to delegate to a subagent:
uv run ash chat "Create an implementation plan for adding OAuth login; use the plan agent"Or delegate general execution:
uv run ash chat "Use the task agent to inspect this repo and summarize test coverage gaps"The main agent decides whether to delegate and then merges the subagent result into the final reply.
Configure Agents
Override built-in agent settings in config.toml:
[agents.task]model = "default" # Optional model alias overridemax_iterations = 25 # Optional iteration cap for this agent
[agents.plan]model = "default"max_iterations = 10Use higher iteration limits only for workflows that need more tool rounds.
How Execution Works
Delegation lifecycle:
- Main agent receives a user request.
- Main agent issues
use_agentwhen delegation is appropriate. - Subagent runs its own loop (LLM -> tools -> LLM) up to
max_iterations. - Subagent returns structured output.
- Main agent responds to the user with that output integrated.
Nested Agent Execution
Ash supports nested delegation (agent -> child agent/skill -> deeper child) using a managed execution stack.
How nested execution behaves:
- Parent frame starts and calls a delegation tool (
use_agentoruse_skill). - Child frame is pushed with its own session, model, and tool scope.
- Child runs until complete, interrupted, or max-iteration/error exit.
- Child result is returned to the parent frame.
- Parent resumes from the waiting tool call and continues execution.
This lets complex workflows compose multiple specialized workers without losing parent task context.
Troubleshooting
Agent does not trigger
# Confirm the request clearly asks for delegationuv run ash chat "Use the plan agent to propose phases for migrating to pydantic v2"If the task is simple, Ash may answer directly without delegation.
Agent stops early
Increase the agent’s iteration cap:
[agents.task]max_iterations = 40Agent output quality is poor
Try a stronger model alias for that agent:
[agents.plan]model = "codex"Runtime/tool issues inside agent execution
uv run ash doctoruv run ash sandbox statusBuild A Custom Subagent
For contributors adding a built-in agent:
- Create an agent class in
src/ash/agents/builtin/. - Return
AgentConfig(name,description,system_prompt, tool scope, limits). - Register it in
src/ash/agents/builtin/__init__.py.
Minimal shape:
from ash.agents.base import Agentfrom ash.agents.types import AgentConfig
class MyAgent(Agent): @property def config(self) -> AgentConfig: return AgentConfig( name="my-agent", description="One-line description", system_prompt="You are a specialized assistant...", allowed_tools=["read_file", "bash"], max_iterations=15, )Reference (Advanced)
Key files:
src/ash/agents/base.py- base class and prompt assemblysrc/ash/agents/types.py-AgentConfig,AgentContext,AgentResultsrc/ash/agents/executor.py- execution loop and delegation runtimesrc/ash/agents/registry.py- agent registration/lookupsrc/ash/agents/builtin/plan.py-planagentsrc/ash/agents/builtin/task.py-taskagent
The use_agent tool is the public delegation entrypoint used by the main agent.