Extending the Demo Agent
The demo content builder agent ships with a researcher subagent, web search, and image generation tools. You can add your own tools, subagents, and skills without any extra OpenBox configuration — governance automatically covers all new tool calls.
This guide assumes you've completed the Deep Agents Integration Guide and have the demo running locally. See the Demo Architecture Reference for the full middleware lifecycle.
How the Demo Is Structured
The content builder agent uses four DeepAgents extension points — all configured through files on disk:
| Extension Point | What It Does | How the LLM Sees It |
|---|---|---|
Memory (AGENTS.md) | Brand voice, writing standards, content pillars | Loaded as persistent system context |
Skills (skills/) | Structured workflows for content types | Activated when the task matches the skill description |
Tools (Python @tool functions) | Capabilities like search, image generation | Available as callable functions |
Subagents (subagents.yaml) | Delegated specialists (e.g., researcher) | Dispatched via the task tool |
Project Structure
| Path | Purpose |
|---|---|
content_writer.py | Agent factory — wires up tools, subagents, skills, and OpenBox middleware |
AGENTS.md | Brand voice and writing standards (loaded as memory) |
skills/blog-post/SKILL.md | Blog post workflow — research, structure, image generation |
skills/social-media/SKILL.md | Social media workflow — LinkedIn, Twitter/X formats |
subagents.yaml | Subagent definitions — name, description, system prompt, tools |
.env | API keys and configuration |
pyproject.toml | Python dependencies |
Adding a Tool
Step 1: Define the Tool
Create a @tool-decorated function. LangChain uses the docstring and type hints to generate the tool schema for the LLM:
from langchain_core.tools import tool
@tool
def fetch_page(url: str) -> str:
"""Fetch the content of a web page.
Args:
url: The URL to fetch
Returns:
The page content as plain text.
"""
import httpx
response = httpx.get(url, follow_redirects=True, timeout=30)
return response.text[:5000]
Step 2: Register the Tool
Add it to the create_deep_agent() call in your agent factory:
return create_deep_agent(
model=init_chat_model("openai:gpt-4o-mini", temperature=0),
tools=[generate_cover, generate_social_image, fetch_page], # Added
# ...
)
Step 3: Classify the Tool (Optional)
If you want category-level governance policies, add it to tool_type_map:
openbox_middleware = create_openbox_middleware(
# ...
tool_type_map={
"web_search": "http",
"fetch_page": "http", # Added — same policy as web_search
},
)
This appends {"__openbox": {"tool_type": "http"}} to the tool's activity input, enabling Rego policies like:
result := {"decision": "REQUIRE_APPROVAL"} if {
input.event_type == "ToolStarted"
some item in input.activity_input
item["__openbox"].tool_type == "http"
}
Adding a Subagent
Step 1: Define the Subagent
Add an entry to subagents.yaml:
editor:
description: >
Use this to review and improve written content.
Checks for clarity, grammar, tone consistency, and factual accuracy.
model: openai:gpt-4o-mini
system_prompt: |
You are an editor. Review the content for:
1. Clarity and readability
2. Grammar and spelling
3. Tone consistency with the brand voice
4. Factual accuracy
Read the file, make improvements, and save the edited version.
If the subagent needs tools, list them:
fact_checker:
description: >
Verifies claims and statistics in content by searching for sources.
model: openai:gpt-4o-mini
system_prompt: |
You are a fact checker. For each claim:
1. Search for the original source
2. Verify the accuracy
3. Save a fact-check report
tools:
- web_search
Step 2: Register the Subagent
The load_subagents() function in content_writer.py reads subagents.yaml automatically. Update known_subagents in the middleware to enable per-subagent governance:
subagent_defs = load_subagents(EXAMPLE_DIR / "subagents.yaml")
known_subagents = [s["name"] for s in subagent_defs] + ["general-purpose"]
openbox_middleware = create_openbox_middleware(
# ...
known_subagents=known_subagents, # Includes your new subagent
)
The SDK automatically classifies task calls to known subagents as a2a and includes the subagent name in governance metadata.
Adding a Skill
Skills are structured workflow instructions that DeepAgents activates when the user's task matches the skill description.
Step 1: Create the Skill File
Create a directory under skills/ with a SKILL.md file:
---
name: newsletter
description: Writes email newsletters with subject lines, preview text,
and structured sections. Use when the user asks to write a newsletter,
email digest, or weekly update.
---
# Newsletter Writing Skill
## Research First (Required)
Before writing, delegate research to the researcher subagent.
## Output Structure
newsletters/<slug>/
├── newsletter.md # The newsletter content
└── subject.txt # Subject line and preview text
## Newsletter Structure
1. Subject line (under 50 characters)
2. Preview text (under 90 characters)
3. Hero section with key insight
4. 3-4 content sections
5. Call-to-action
Step 2: Register the Skill
Add the skills directory to your create_deep_agent() call (already configured in the demo):
return create_deep_agent(
skills=["./skills/"], # Loads all SKILL.md files in subdirectories
# ...
)
DeepAgents discovers skills by scanning the directory for SKILL.md files. No additional registration needed.
Customizing Brand Voice
Edit AGENTS.md to change the agent's personality and writing standards. This file is loaded as persistent memory and shapes all content output:
# My Company Agent
## Brand Voice
- **Technical and precise**: Write for a developer audience
- **No marketing fluff**: Facts and code examples over buzzwords
## Writing Standards
1. Include code examples in every technical post
2. Link to official documentation
3. Use American English spelling
Checklist
Adding a Tool
- Create a
@tool-decorated function with clear docstring and type hints - Add to the
toolslist increate_deep_agent() - (Optional) Add to
tool_type_mapfor category-level policies - If the tool needs API keys, add to
.envand.env.example
Adding a Subagent
- Add entry to
subagents.yamlwith name, description, system prompt - If it needs tools, list them under
tools:and ensure the tool function is inavailable_toolsinload_subagents() - Verify
known_subagentsincludes the new name (automatic if usingload_subagents())
Adding a Skill
- Create
skills/<name>/SKILL.mdwith frontmatter (name,description) - Define the workflow structure and output format
- Ensure
skills=["./skills/"]is set increate_deep_agent()
Next Steps
- Configuration — Fine-tune timeouts, fail policies, and tool classification
- Error Handling — Handle governance decisions in your code
- Configure Trust Controls — Set up guardrails, policies, and behavioral rules
- Demo Architecture Reference — Middleware lifecycle, event flow, and subagent dispatch