Skip to content

Architecture

CodeBuddy is a deepagentsjs agent extended with an IDE-native tool set, custom middleware, and a routed backend. This page maps every piece and how they connect.

DeveloperAgent.create() returns a standard LangGraph runnable produced by createDeepAgent(). What it plugs in:

SlotWired to
modelbuildChatModel() — resolves the active provider (9 supported) from user settings
systemPromptbase prompt + ProjectRulesService + MemoryTool.getFormattedMemories() + SkillManager.getSkillsPrompt()
toolsToolProvider.getToolsAsync() — 27+ core tools + dynamically loaded MCP tools
subagents8 specialists via createDeveloperSubagents(); deepagents adds a 9th general-purpose
backendCompositeBackend — routes /workspace/ → real FS, /docs/ → Store, / → State
middlewareBuilt-in todoList + filesystem + subAgent + custom Memory + Skills
interruptOndelete_file requires modal approval; configurable per-tool
storeInMemoryStore — persists /docs/ across conversations
checkpointerSqlJsCheckpointSaver (SQLite WASM), falls back to MemorySaver

The graph LangGraph returns supports streaming, HITL, memory, and LangSmith Studio out of the box. Nothing custom.

sequenceDiagram participant User participant AS as AgentService participant DA as Developer Agent participant MW as Middleware stack participant CB as CompositeBackend participant SA as Subagent pool participant TP as ToolProvider User->>AS: Message AS->>DA: Create stream DA->>MW: Init (5 layers) MW-->>DA: Prompt + tools DA->>DA: Reason (LangGraph loop) alt Simple task DA->>TP: Invoke tool (permission-scoped) TP->>CB: Read / write CB-->>TP: Result TP-->>DA: Output else Delegated task DA->>SA: task({subagent_type, description}) SA->>TP: Invoke role-filtered tools TP->>CB: Read / write CB-->>SA: Result SA-->>DA: ToolMessage end DA-->>AS: Stream chunks AS-->>User: Render

Order matters — each layer wraps the next.

LayerSourceProvides
todoListdeepagentswrite_todos — task planning + progress tracking
filesystemdeepagentsls, read_file, write_file, edit_file, glob, grep
subAgentdeepagentstask tool — spawns a specialist with context isolation
memoryCodeBuddyReads AGENTS.md / project rules, injects into the system prompt
skillsCodeBuddyLoads .codebuddy/skills/, adds prompts + tools

A failing custom middleware logs a warning; the agent still starts. Built-in middleware failures are fatal (deepagents contract).

createDeveloperSubagents() returns 8 role-filtered specialists. The 9th (general-purpose) is added by deepagents itself and inherits the full parent tool set.

SubagentFocus
code-analyzerReview, bug detection, architecture analysis
doc-writerTechnical docs, API references, ADRs
debuggerRoot-cause via Debug Adapter Protocol
file-organizerDirectory restructuring, moves, import updates
architectSystem design, pattern selection
reviewerCode quality + security review
testerTest creation, execution, failure analysis
architecture-expertRepo-structure Q&A over static analysis
general-purposeAuto-included; inherits all parent tools + skills

When the main agent calls task({subagent_type, description}), deepagents constructs a new ReactAgent with the subagent config, runs it to completion, returns the result as a ToolMessage, and destroys the instance. Subagents run in parallel when tasks are independent.

Deep dive: Subagents.

CompositeBackend routes file operations to different storage layers based on path prefix.

RouteBackendPersistenceUsed for
/workspace/VscodeFsBackendReal filesystemActual project files (via ripgrep + VS Code FS API)
/docs/StoreBackendLangGraph StoreLong-lived docs, ADRs, refs — survives sessions
/ (default)StateBackendLangGraph StateEphemeral scratch — conversation-scoped

VscodeFsBackend adds ripgrep for fast search, SimpleMutex for atomic writes, TOCTOU-resistant validatePathWithinWorkspace() on every path, and diff-review integration on writes.

ToolProvider builds the tool list at agent construction. Broadly:

CategoryExamples
File opsread_file, write_file, edit_file, ast_edit, list_files, compose_files, find_files
Searchripgrep_search, search_symbols, search_vector_db, web_search
Editor / LSPget_active_editor, lsp_query, get_diagnostics, query_graph
Executionmanage_terminal, run_terminal_command, run_tests, run_skill_script
Debuggingdebug_get_state, debug_get_stack_trace, debug_get_variables, debug_evaluate, debug_control (5)
Browserbrowser — Playwright automation
Knowledgemanage_core_memory, manage_tasks, think, get_architecture_knowledge
Integrationsgit_ops, git_read, open_web_preview, standup_intelligence, team_graph

Every tool passes through ToolProvider.applyPermissionFilter → filter by security profile → wrap with ToolRateLimiter (600/min global, 200/min per-tool).

MCP tools load lazily (5-min cache, per-server circuit breaker). See MCP.

The AgentSafetyGuard caps every task:

  • 15000 stream events
  • 2000 tool calls
  • 60-minute wall clock
  • Consecutive-failure circuit breaker
  • Context-window compaction when message history exceeds threshold

Hitting any limit ends the stream cleanly with a diagnostic message; the diff view stays empty.

When a provider fails, ProviderFailoverService classifies the reason (auth / rate_limit / billing / timeout / overloaded) and can switch to an alternate. Transient network errors get 2 auto-retries with exponential backoff. Catastrophic shell patterns (rm -rf /, mkfs, fork bombs) deny in all permission profiles.

Deep dive: Self-healing.

9 providers behind one ChatModel type — Anthropic, OpenAI, Google Gemini, Groq, DeepSeek, xAI Grok, Qwen, GLM, plus a Local slot covering Ollama, LM Studio, Docker, and any OpenAI-API-compatible endpoint. Switching providers is one setting change; the graph is provider-agnostic.

Cost tracked per-token per-model via CostTrackingService; see Cost tracking.