Skip to main content
Last updated on

Demo Architecture Reference

Quick reference for the content builder agent architecture. For setup, see the Integration Guide. For customization, see Extending the Demo Agent.

System Layers

LayerTechnologyRole
AgentDeepAgents, LangChainRuns the agent loop, dispatches tools and subagents
GovernanceOpenBox MiddlewareIntercepts model and tool calls for policy evaluation
ExternalOpenAI, Tavily, Gemini, OpenBoxLLM providers, search, image generation, trust engine

Middleware Hooks Lifecycle

The OpenBoxMiddleware implements 4 async hooks (plus 4 sync variants) that DeepAgents calls at runtime:

Hook Details

HookWhenWhat OpenBox Does
abefore_agentBefore agent graph runsSends SignalReceived, WorkflowStarted, pre-screen LLMStarted; caches guardrails response
awrap_model_callBefore every LLM callRuns PII redaction on prompt; sends LLMStarted/LLMCompleted with token counts
awrap_tool_callBefore every tool executionClassifies tool type; enriches with __openbox metadata; sends ToolStarted/ToolCompleted
aafter_agentAfter agent graph completesSends WorkflowCompleted; cleans up span processor state

Governance Event Flow

Every agent invocation produces this sequence of events sent to OpenBox Core:

#EventTriggerKey Data
1SignalReceivedUser prompt arrivessignal_name: "user_prompt", prompt text
2WorkflowStartedAgent beginsAgent state, workflow ID, thread ID
3LLMStartedPre-screenUser prompt for guardrails check
4LLMStartedEach model callPrompt messages (after PII redaction)
5LLMCompletedModel respondsToken counts, model name, completion text
6ToolStartedEach tool callTool name, args, __openbox metadata
7ToolCompletedTool returnsOutput, duration, OTel spans
8WorkflowCompletedAgent finishesFinal output, status

Verdict Enforcement

VerdictBehavior
ALLOWTool/LLM executes normally
BLOCKGovernanceBlockedError raised — single tool blocked, agent may continue
HALTGovernanceHaltError raised — entire session terminated
REQUIRE_APPROVALMiddleware polls for human decision; proceeds or halts based on response

Subagent Dispatch

When the agent calls the task tool to dispatch a subagent, the middleware:

  1. Detects the subagent — extracts subagent_type from tool args via resolve_subagent_from_tool_call()
  2. Classifies as a2a — if the subagent name is in known_subagents
  3. Enriches activity input — appends __openbox sentinel for Rego targeting:
{
"description": "Research AI agents and save to research/ai-agents.md",
"subagent_type": "researcher",
"__openbox": {
"tool_type": "a2a",
"subagent_name": "researcher"
}
}

Built-in Tool Detection

The SDK recognizes DeepAgents built-in tools and treats them differently:

DEEPAGENT_BUILTIN_TOOLS = frozenset({
"write_todos", "ls", "read_file", "write_file", "edit_file",
"glob", "grep", "execute", "task"
})

Only the task tool triggers subagent detection. Other built-in tools are governed as regular tool calls.

Tool Classification

Tool types are resolved in priority order:

PrioritySourceExample
1tool_type_map (explicit)"web_search""http"
2Subagent detection (automatic)"task" + researcher → "a2a"
3None (default)"generate_cover" → governed by default policies

Classified tools get __openbox metadata appended to their activity input, enabling category-level Rego policies.

OpenTelemetry Instrumentation

The middleware uses a WorkflowSpanProcessor to capture HTTP calls, database queries, and file I/O during tool execution:

  1. Before a tool runs, the middleware registers a trace context with the span processor
  2. During tool execution, OTel auto-instrumentation captures outbound HTTP requests
  3. After the tool completes, captured spans are attached to the ToolCompleted event
  4. The span processor cleans up on WorkflowCompleted

This gives OpenBox visibility into what external calls each tool makes — not just the tool's input/output, but the actual HTTP requests to OpenAI, Tavily, etc.

Pre-Screen Optimization

The first LLM call in each invocation reuses the pre-screen guardrails response from abefore_agent. This avoids a duplicate governance call:

  1. abefore_agent sends LLMStarted with the user prompt → gets verdict + PII redaction
  2. awrap_model_call detects _first_llm_call=True → reuses cached _pre_screen_response
  3. Subsequent LLM calls go through the full governance path

Key Files

PathPurpose
content_writer.pyAgent factory — create_content_writer() integration point
AGENTS.mdBrand voice and writing standards (loaded as memory)
subagents.yamlSubagent definitions — name, description, tools
skills/blog-post/SKILL.mdBlog post workflow with research, structure, image generation
skills/social-media/SKILL.mdSocial media workflow for LinkedIn and Twitter/X
.envAPI keys and OpenBox configuration

SDK Source Files

PathPurpose
openbox_deepagent/__init__.pyPublic API — re-exports errors, types, middleware
openbox_deepagent/middleware_factory.pycreate_openbox_middleware() factory function
openbox_deepagent/middleware.pyOpenBoxMiddleware class — hooks and state management
openbox_deepagent/middleware_hooks.pyStateless hook implementations — event construction and governance calls
openbox_deepagent/subagent_resolver.pySubagent detection, built-in tool constants, HITL conflict detection