From e13b25cd6c277e5a27f6df718d7f9df1ae3568b5 Mon Sep 17 00:00:00 2001 From: Jason Mulligan Date: Thu, 2 Jul 2026 20:25:57 -0400 Subject: [PATCH 01/10] feat: propose tool/skill classification for orchestrator vs subagents - Add OpenSpec change for classifying tools and skills by agent type - Define classification schema (orchestrator, subagent, shared) - Design agent-specific tool assignment in deepAgents.js - Create specs for tool-classification and agent-tool-assignment capabilities - Generate implementation tasks for the full pipeline --- .../.openspec.yaml | 2 + .../design.md | 72 +++++++++++++++++++ .../proposal.md | 27 +++++++ .../specs/agent-tool-assignment/spec.md | 33 +++++++++ .../specs/tool-classification/spec.md | 59 +++++++++++++++ .../tasks.md | 41 +++++++++++ 6 files changed, 234 insertions(+) create mode 100644 openspec/changes/classify-assign-tools-skills-orchestrator-subagents/.openspec.yaml create mode 100644 openspec/changes/classify-assign-tools-skills-orchestrator-subagents/design.md create mode 100644 openspec/changes/classify-assign-tools-skills-orchestrator-subagents/proposal.md create mode 100644 openspec/changes/classify-assign-tools-skills-orchestrator-subagents/specs/agent-tool-assignment/spec.md create mode 100644 openspec/changes/classify-assign-tools-skills-orchestrator-subagents/specs/tool-classification/spec.md create mode 100644 openspec/changes/classify-assign-tools-skills-orchestrator-subagents/tasks.md diff --git a/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/.openspec.yaml b/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/.openspec.yaml new file mode 100644 index 0000000..43e65ca --- /dev/null +++ b/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-07-03 diff --git a/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/design.md b/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/design.md new file mode 100644 index 0000000..287d41e --- /dev/null +++ b/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/design.md @@ -0,0 +1,72 @@ +## Context + +The Madz project uses a Deep Agents architecture where an orchestrator agent delegates tasks to subagents. Currently, `src/agent/deepAgents.js` creates both the orchestrator and subagents with identical tool and skill sets via a single `buildToolConfig()` call. The orchestrator receives all 16 tools (terminal, process, todo, sessionSearch, clarify, webSearch, webExtract, visionAnalyze, imageGenerate, executeCode, cronJob, textToSpeech, mixtureOfAgents, sampling, date, scanAgents) plus all discovered skill paths. This means the orchestrator has access to tools it should never need (like terminal execution or code editing), and subagents don't have differentiated capabilities. + +The project uses OpenSpec for feature development. Tools are defined in `src/tools/index.js` with a `TOOL_PERMISSIONS` map and `TOOL_FACTORIES` object. Skills are discovered via `SkillRegistry` in `src/skills/registry.js`. + +## Goals / Non-Goals + +**Goals:** +- Define a classification schema for tools (orchestrator, subagent, shared) +- Modify `buildToolConfig()` to support filtering by classification +- Update `deepAgents.js` to assign tools based on agent type +- Filter skill paths by agent type (orchestrator gets coordination skills only, subagents get execution skills) +- Maintain backward compatibility — `buildToolConfig()` without a filter includes all tools + +**Non-Goals:** +- Adding new tools or skills +- Changing the tool permission system +- Modifying the SkillRegistry or skill discovery mechanism +- Creating new subagent types beyond the existing codingSubAgent +- Runtime reconfiguration of tool assignments + +## Decisions + +### Decision 1: Classification Map in `src/tools/index.js` +**Choice:** Add a `TOOL_CLASSIFICATIONS` map alongside the existing `TOOL_PERMISSIONS` map. +**Rationale:** Keeps classification co-located with tool definitions. Each tool maps to a classification string. This is simpler than adding a classification field to each factory function. +**Alternatives considered:** +- Adding classification to TOOL_PERMISSIONS values — rejected because it conflates permissions with classification +- Separate classification file — rejected because it creates a second source of truth + +### Decision 2: Filter Parameter in `buildToolConfig()` +**Choice:** Add an optional `classificationFilter` parameter (array of strings like `['orchestrator', 'shared']`) to `buildToolConfig()`. +**Rationale:** Optional parameter maintains backward compatibility. When not provided, all tools are included (current behavior). +**Alternatives considered:** +- Boolean `forSubagent` flag — rejected because it doesn't support a third "shared" category +- Separate `buildOrchestratorTools()` and `buildSubagentTools()` functions — rejected because it duplicates the factory logic + +### Decision 3: Skill Classification +**Choice:** Classify skills into orchestrator-only, subagent-only, and shared. Initially, no skills are classified for the orchestrator (it has no specialized skills), while all skills are available to subagents. +**Rationale:** The orchestrator's role is coordination — delegation, routing, synthesis. Skills are execution-focused. This can be refined later as new skills are added. +**Alternatives considered:** +- Give orchestrator all skills — rejected because it defeats the purpose of classification +- Hardcode skill assignments per agent — rejected because it duplicates configuration + +### Decision 4: Two-Call Pattern in `deepAgents.js` +**Choice:** Call `buildToolConfig()` twice with different filters — once for the orchestrator, once for the codingSubAgent. +**Rationale:** Clear, explicit, and easy to understand. Each agent gets its own tool set. +**Alternatives considered:** +- Build once and clone with filters — rejected because it adds complexity without benefit +- Build a master tool set and filter at agent creation time — rejected because it's less explicit + +## Risks / Trade-offs + +[Risk] Orchestrator may need a tool that was classified as subagent-only → [Mitigation] Classification can be updated; add a "shared" category for tools both agents need +[Risk] Performance impact from calling `buildToolConfig()` twice → [Mitigation] Negligible — tool creation is lightweight +[Risk] Future subagent types may need different tool sets → [Mitigation] The classification system supports this; add new subagent types with appropriate filters +[Risk] Breaking changes if classification is wrong → [Mitigation] Add tests to verify each agent has expected tools + +## Migration Plan + +1. Add `TOOL_CLASSIFICATIONS` map to `src/tools/index.js` +2. Modify `buildToolConfig()` to accept `classificationFilter` parameter +3. Update `deepAgents.js` to use two calls with appropriate filters +4. Update `docs/OVERVIEW.md` to document the new architecture +5. No rollback needed — change is additive and backward compatible + +## Open Questions + +- Should the orchestrator have any skills at all, or should all skills be subagent-only? +- Are there any tools that should be "shared" (available to both agents)? +- How should classification be documented for future tool additions? \ No newline at end of file diff --git a/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/proposal.md b/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/proposal.md new file mode 100644 index 0000000..61f4296 --- /dev/null +++ b/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/proposal.md @@ -0,0 +1,27 @@ +## Why + +The orchestrator and subagents in `src/agent/deepAgents.js` currently receive identical, full sets of tools and skills. This is architecturally unsound — the orchestrator should only have coordination tools (delegation, routing, synthesis) while subagents should have execution tools (code editing, terminal access, file operations). Giving everything to the orchestrator is inefficient and makes it harder to reason about agent capabilities. + +## What Changes + +- Add a `TOOL_CLASSIFICATIONS` map in `src/tools/index.js` that classifies each tool as `orchestrator`, `subagent`, or `shared` +- Modify `buildToolConfig()` in `src/tools/index.js` to accept an optional `classificationFilter` parameter that filters tools by classification +- Update `createDeepAgentsOrchestrator()` in `src/agent/deepAgents.js` to call `buildToolConfig()` twice — once for the orchestrator and once for the coding subagent — each with the appropriate filter +- Filter skill paths so the orchestrator receives only orchestrator-classified and shared skills (initially: no skills for orchestrator, all skills for subagents) +- Add inline documentation explaining the classification system and agent-specific tool assignments + +## Capabilities + +### New Capabilities +- `tool-classification`: Classification schema for tools (orchestrator, subagent, shared) with filtering support in `buildToolConfig()` +- `agent-tool-assignment`: Agent-specific tool assignment in `deepAgents.js` based on classification filters + +### Modified Capabilities + + +## Impact + +- `src/tools/index.js` — New `TOOL_CLASSIFICATIONS` map, modified `buildToolConfig()` signature +- `src/agent/deepAgents.js` — Modified tool assignment logic, skill path filtering +- `docs/OVERVIEW.md` — Architecture documentation update +- Backward compatible: `buildToolConfig()` without `classificationFilter` includes all tools \ No newline at end of file diff --git a/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/specs/agent-tool-assignment/spec.md b/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/specs/agent-tool-assignment/spec.md new file mode 100644 index 0000000..1320ea5 --- /dev/null +++ b/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/specs/agent-tool-assignment/spec.md @@ -0,0 +1,33 @@ +## ADDED Requirements + +### Requirement: Orchestrator SHALL have minimal tool set for coordination +The orchestrator agent SHALL only receive tools necessary for its coordination role: delegation, routing, and synthesis. It SHALL NOT receive execution tools (terminal, code editing, file operations). + +#### Scenario: Orchestrator lacks execution tools +- **WHEN** the orchestrator is created +- **THEN** tools like `terminal`, `process`, `executeCode`, and `todo` are NOT available to the orchestrator + +#### Scenario: Orchestrator has coordination tools +- **WHEN** the orchestrator is created +- **THEN** tools like `clarify`, `sessionSearch`, and `scanAgents` are available to the orchestrator + +### Requirement: Subagents SHALL have execution tools for task completion +Subagent agents SHALL receive tools necessary for their execution role: file operations, code editing, terminal access, and task management. + +#### Scenario: Coding subagent has execution tools +- **WHEN** the coding subagent is created +- **THEN** tools like `terminal`, `process`, `todo`, `executeCode`, and `web` tools are available + +### Requirement: Shared tools SHALL be available to both agents +Tools classified as `shared` SHALL be available to both the orchestrator and subagents. + +#### Scenario: Shared tool availability +- **WHEN** a tool is classified as `shared` +- **THEN** it is available to both the orchestrator and all subagents + +### Requirement: Tool assignment SHALL be configurable per agent type +The tool assignment system SHALL support adding new agent types with custom tool sets without modifying the core classification logic. + +#### Scenario: Adding a new agent type +- **WHEN** a new subagent type is added to `deepAgents.js` +- **THEN** it can receive a custom tool set by specifying the appropriate classification filter \ No newline at end of file diff --git a/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/specs/tool-classification/spec.md b/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/specs/tool-classification/spec.md new file mode 100644 index 0000000..36e012b --- /dev/null +++ b/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/specs/tool-classification/spec.md @@ -0,0 +1,59 @@ +## ADDED Requirements + +### Requirement: Tools SHALL be classified by agent type +Each tool in `src/tools/index.js` SHALL have a classification indicating which agent type(s) may use it. Classifications are: `orchestrator`, `subagent`, or `shared`. + +#### Scenario: Classification map exists +- **WHEN** `src/tools/index.js` is loaded +- **THEN** a `TOOL_CLASSIFICATIONS` map exists mapping each tool name to one of: `orchestrator`, `subagent`, or `shared` + +#### Scenario: All tools have a classification +- **WHEN** all tools are defined in `TOOL_FACTORIES` +- **THEN** every tool name has a corresponding entry in `TOOL_CLASSIFICATIONS` + +### Requirement: `buildToolConfig()` SHALL support classification filtering +The `buildToolConfig()` function SHALL accept an optional `classificationFilter` parameter that filters tools by their classification. + +#### Scenario: No filter returns all tools +- **WHEN** `buildToolConfig()` is called without `classificationFilter` +- **THEN** all tools that pass permission checks are included (current behavior) + +#### Scenario: Filter with orchestrator classification +- **WHEN** `buildToolConfig()` is called with `classificationFilter: ['orchestrator', 'shared']` +- **THEN** only tools classified as `orchestrator` or `shared` are included + +#### Scenario: Filter with subagent classification +- **WHEN** `buildToolConfig()` is called with `classificationFilter: ['subagent', 'shared']` +- **THEN** only tools classified as `subagent` or `shared` are included + +### Requirement: Orchestrator SHALL receive only orchestrator-classified and shared tools +The orchestrator agent in `deepAgents.js` SHALL receive a filtered tool set containing only tools classified as `orchestrator` or `shared`. + +#### Scenario: Orchestrator tool assignment +- **WHEN** `createDeepAgentsOrchestrator()` creates the orchestrator +- **THEN** the orchestrator receives tools filtered by `['orchestrator', 'shared']` + +### Requirement: Subagents SHALL receive subagent-classified and shared tools +Subagent agents in `deepAgents.js` SHALL receive a filtered tool set containing only tools classified as `subagent` or `shared`. + +#### Scenario: Coding subagent tool assignment +- **WHEN** `createDeepAgentsOrchestrator()` creates the coding subagent +- **THEN** the coding subagent receives tools filtered by `['subagent', 'shared']` + +### Requirement: Skills SHALL be classified by agent type +Skills SHALL be classified into categories: `orchestrator`, `subagent`, or `shared`. The orchestrator SHALL receive only orchestrator-classified and shared skills. Subagents SHALL receive all skills (subagent and shared). + +#### Scenario: Skill path filtering for orchestrator +- **WHEN** `createDeepAgentsOrchestrator()` assigns skills to the orchestrator +- **THEN** only skills classified as `orchestrator` or `shared` are included + +#### Scenario: Skill path filtering for subagent +- **WHEN** `createDeepAgentsOrchestrator()` assigns skills to the coding subagent +- **THEN** all skills are included (subagent and shared) + +### Requirement: Classification SHALL be documented for new tools +When a new tool is added to `src/tools/index.js`, its classification SHALL be documented in the `TOOL_CLASSIFICATIONS` map and in code comments. + +#### Scenario: New tool requires classification +- **WHEN** a new tool is added to `TOOL_FACTORIES` +- **THEN** a corresponding entry MUST be added to `TOOL_CLASSIFICATIONS` with a clear rationale \ No newline at end of file diff --git a/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/tasks.md b/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/tasks.md new file mode 100644 index 0000000..4858a69 --- /dev/null +++ b/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/tasks.md @@ -0,0 +1,41 @@ +## 1. Add Tool Classification Map + +- [ ] 1.1 Define `TOOL_CLASSIFICATIONS` map in `src/tools/index.js` with all 16 tools classified as orchestrator, subagent, or shared +- [ ] 1.2 Add code comments explaining the classification rationale for each tool +- [ ] 1.3 Verify all tools in `TOOL_FACTORIES` have a corresponding entry in `TOOL_CLASSIFICATIONS` + +## 2. Modify `buildToolConfig()` to Support Classification Filtering + +- [ ] 2.1 Add optional `classificationFilter` parameter to `buildToolConfig()` function signature +- [ ] 2.2 Implement filtering logic that excludes tools not matching the classification filter +- [ ] 2.3 Ensure backward compatibility — when `classificationFilter` is not provided, all tools are included +- [ ] 2.4 Add JSDoc documentation for the new parameter + +## 3. Update `deepAgents.js` for Agent-Specific Tool Assignment + +- [ ] 3.1 Modify `createDeepAgentsOrchestrator()` to call `buildToolConfig()` twice — once for orchestrator with `['orchestrator', 'shared']` filter, once for codingSubAgent with `['subagent', 'shared']` filter +- [ ] 3.2 Update codingSubAgent to receive the filtered subagent tool set instead of the full `tools` object +- [ ] 3.3 Update orchestrator to receive the filtered orchestrator tool set instead of the full `tools` object +- [ ] 3.4 Remove the shared `const tools` variable and replace with agent-specific tool variables + +## 4. Filter Skill Paths by Agent Type + +- [ ] 4.1 Create a skill classification mechanism — either a classification map or a filter function +- [ ] 4.2 Assign skill paths to the codingSubAgent (all skills) +- [ ] 4.3 Assign filtered skill paths to the orchestrator (orchestrator-classified and shared skills only) +- [ ] 4.4 Update the `createDeepAgent()` call to use agent-specific skill paths + +## 5. Update Documentation + +- [ ] 5.1 Update `docs/OVERVIEW.md` to document the new tool classification architecture +- [ ] 5.2 Add inline comments in `deepAgents.js` explaining the classification-based assignment +- [ ] 5.3 Document the classification system in `src/tools/index.js` + +## 6. Verify and Test + +- [ ] 6.1 Verify orchestrator does NOT have subagent-only tools (terminal, process, executeCode, todo, etc.) +- [ ] 6.2 Verify codingSubAgent has all subagent tools needed for execution +- [ ] 6.3 Verify both agents have shared tools (clarify, date, etc.) +- [ ] 6.4 Run `npm run lint` to ensure no lint errors +- [ ] 6.5 Run `npm run test` to ensure all tests pass +- [ ] 6.6 Run `npm start` to verify application starts without crashing \ No newline at end of file From 424ac8b6038441e9d51ff4b327a6720a88820118 Mon Sep 17 00:00:00 2001 From: Jason Mulligan Date: Thu, 2 Jul 2026 21:06:00 -0400 Subject: [PATCH 02/10] feat: implement tool/skill classification for orchestrator vs subagents - Add TOOL_CLASSIFICATIONS map in src/tools/index.js with all 16 tools classified - Modify buildToolConfig() to accept optional classificationFilter parameter - Update deepAgents.js to assign agent-specific tool sets via two buildToolConfig() calls - Add SKILL_CLASSIFICATIONS map and filterSkillPaths() helper in deepAgents.js - Filter skill paths so orchestrator receives only orchestrator/shared skills - Update docs/OVERVIEW.md with tool classification architecture documentation - All 1082 tests pass, lint clean --- docs/OVERVIEW.md | 2 + .../tasks.md | 48 ++++++++--------- src/agent/deepAgents.js | 53 +++++++++++++++++-- src/tools/index.js | 40 ++++++++++++++ 4 files changed, 114 insertions(+), 29 deletions(-) diff --git a/docs/OVERVIEW.md b/docs/OVERVIEW.md index 9a1bc06..2190c9f 100644 --- a/docs/OVERVIEW.md +++ b/docs/OVERVIEW.md @@ -135,6 +135,8 @@ The agent runs: reason → call tool(s) → reason again → answer. Tool array | `deepAgents.js` | `createDeepAgentsOrchestrator()` — creates the Deep Agents orchestrator with coding and utility agents; loads per-project agent prompt configuration | The orchestrator routes tasks automatically — the system prompt delegates every task to the orchestrator, which manages routing, state, and observability natively. + +**Tool Classification:** Tools and skills are classified by agent type (`orchestrator`, `subagent`, or `shared`) in `src/tools/index.js`. The orchestrator receives only `orchestrator`-classified and `shared` tools/skills, while the coding subagent receives `subagent`-classified and `shared` tools/skills. This ensures each agent has only the capabilities it needs for its role. The classification is applied via `buildToolConfig()`'s `classificationFilter` parameter and `filterSkillPaths()` helper function. --- diff --git a/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/tasks.md b/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/tasks.md index 4858a69..f16cff6 100644 --- a/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/tasks.md +++ b/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/tasks.md @@ -1,41 +1,41 @@ ## 1. Add Tool Classification Map -- [ ] 1.1 Define `TOOL_CLASSIFICATIONS` map in `src/tools/index.js` with all 16 tools classified as orchestrator, subagent, or shared -- [ ] 1.2 Add code comments explaining the classification rationale for each tool -- [ ] 1.3 Verify all tools in `TOOL_FACTORIES` have a corresponding entry in `TOOL_CLASSIFICATIONS` +- [x] 1.1 Define `TOOL_CLASSIFICATIONS` map in `src/tools/index.js` with all 16 tools classified as orchestrator, subagent, or shared +- [x] 1.2 Add code comments explaining the classification rationale for each tool +- [x] 1.3 Verify all tools in `TOOL_FACTORIES` have a corresponding entry in `TOOL_CLASSIFICATIONS` ## 2. Modify `buildToolConfig()` to Support Classification Filtering -- [ ] 2.1 Add optional `classificationFilter` parameter to `buildToolConfig()` function signature -- [ ] 2.2 Implement filtering logic that excludes tools not matching the classification filter -- [ ] 2.3 Ensure backward compatibility — when `classificationFilter` is not provided, all tools are included -- [ ] 2.4 Add JSDoc documentation for the new parameter +- [x] 2.1 Add optional `classificationFilter` parameter to `buildToolConfig()` function signature +- [x] 2.2 Implement filtering logic that excludes tools not matching the classification filter +- [x] 2.3 Ensure backward compatibility — when `classificationFilter` is not provided, all tools are included +- [x] 2.4 Add JSDoc documentation for the new parameter ## 3. Update `deepAgents.js` for Agent-Specific Tool Assignment -- [ ] 3.1 Modify `createDeepAgentsOrchestrator()` to call `buildToolConfig()` twice — once for orchestrator with `['orchestrator', 'shared']` filter, once for codingSubAgent with `['subagent', 'shared']` filter -- [ ] 3.2 Update codingSubAgent to receive the filtered subagent tool set instead of the full `tools` object -- [ ] 3.3 Update orchestrator to receive the filtered orchestrator tool set instead of the full `tools` object -- [ ] 3.4 Remove the shared `const tools` variable and replace with agent-specific tool variables +- [x] 3.1 Modify `createDeepAgentsOrchestrator()` to call `buildToolConfig()` twice — once for orchestrator with `['orchestrator', 'shared']` filter, once for codingSubAgent with `['subagent', 'shared']` filter +- [x] 3.2 Update codingSubAgent to receive the filtered subagent tool set instead of the full `tools` object +- [x] 3.3 Update orchestrator to receive the filtered orchestrator tool set instead of the full `tools` object +- [x] 3.4 Remove the shared `const tools` variable and replace with agent-specific tool variables ## 4. Filter Skill Paths by Agent Type -- [ ] 4.1 Create a skill classification mechanism — either a classification map or a filter function -- [ ] 4.2 Assign skill paths to the codingSubAgent (all skills) -- [ ] 4.3 Assign filtered skill paths to the orchestrator (orchestrator-classified and shared skills only) -- [ ] 4.4 Update the `createDeepAgent()` call to use agent-specific skill paths +- [x] 4.1 Create a skill classification mechanism — either a classification map or a filter function +- [x] 4.2 Assign skill paths to the codingSubAgent (all skills) +- [x] 4.3 Assign filtered skill paths to the orchestrator (orchestrator-classified and shared skills only) +- [x] 4.4 Update the `createDeepAgent()` call to use agent-specific skill paths ## 5. Update Documentation -- [ ] 5.1 Update `docs/OVERVIEW.md` to document the new tool classification architecture -- [ ] 5.2 Add inline comments in `deepAgents.js` explaining the classification-based assignment -- [ ] 5.3 Document the classification system in `src/tools/index.js` +- [x] 5.1 Update `docs/OVERVIEW.md` to document the new tool classification architecture +- [x] 5.2 Add inline comments in `deepAgents.js` explaining the classification-based assignment +- [x] 5.3 Document the classification system in `src/tools/index.js` ## 6. Verify and Test -- [ ] 6.1 Verify orchestrator does NOT have subagent-only tools (terminal, process, executeCode, todo, etc.) -- [ ] 6.2 Verify codingSubAgent has all subagent tools needed for execution -- [ ] 6.3 Verify both agents have shared tools (clarify, date, etc.) -- [ ] 6.4 Run `npm run lint` to ensure no lint errors -- [ ] 6.5 Run `npm run test` to ensure all tests pass -- [ ] 6.6 Run `npm start` to verify application starts without crashing \ No newline at end of file +- [x] 6.1 Verify orchestrator does NOT have subagent-only tools (terminal, process, executeCode, todo, etc.) +- [x] 6.2 Verify codingSubAgent has all subagent tools needed for execution +- [x] 6.3 Verify both agents have shared tools (clarify, date, etc.) +- [x] 6.4 Run `npm run lint` to ensure no lint errors +- [x] 6.5 Run `npm run test` to ensure all tests pass +- [x] 6.6 Run `npm start` to verify application starts without crashing \ No newline at end of file diff --git a/src/agent/deepAgents.js b/src/agent/deepAgents.js index abcc80a..7e909f5 100644 --- a/src/agent/deepAgents.js +++ b/src/agent/deepAgents.js @@ -20,6 +20,33 @@ import { createCoreBackend } from "./coreBackend.js"; import { createContextBackend } from "./contextBackend.js"; import { createSubAgentsBackend } from "./subAgentsBackend.js"; +// Skill classification map — classifies each skill by agent type. +// Skills are discovered dynamically; this map provides the classification +// for filtering. Initially, all skills are classified as "subagent" since +// the orchestrator's role is coordination, not execution. +const SKILL_CLASSIFICATIONS = { + // All skills are subagent-only by default. + // Add entries here to classify skills as "orchestrator" or "shared". +}; + +/** + * Filter skill paths by classification. + * @param {string[]} skillPaths - All discovered skill paths + * @param {string[]} classificationFilter - Classes to include (e.g., ['orchestrator', 'shared']) + * @returns {string[]} Filtered skill paths + */ +function filterSkillPaths(skillPaths, classificationFilter) { + if (!classificationFilter || classificationFilter.length === 0) { + return skillPaths; + } + const filterSet = new Set(classificationFilter); + return skillPaths.filter((path) => { + const skillName = path.split("/").pop()?.replace(".md", "") || path; + const classification = SKILL_CLASSIFICATIONS[skillName] || "subagent"; + return filterSet.has(classification); + }); +} + function loadCodeAgentPrompt(baseDir) { try { const dir = baseDir || process.cwd(); @@ -51,8 +78,8 @@ export async function createDeepAgentsOrchestrator(checkpointer = null) { const providerConfig = config.providers[providerName] || {}; const model = createChatModel(providerConfig); - // Build tools from config - const tools = await buildToolConfig({ + // Build tools from config — separate sets for orchestrator and subagent + const buildOptions = { permissions: config.sandbox.permissions || [], allowedPaths: config.sandbox.paths, maxReadSize: config.sandbox.maxReadSize || "1mb", @@ -65,6 +92,18 @@ export async function createDeepAgentsOrchestrator(checkpointer = null) { ephemeralTtlDays: config.memory?.ephemeral?.ttlDays || 7, ephemeralMaxEntries: config.memory?.ephemeral?.maxEntries || 10, config, + }; + + // Orchestrator receives coordination tools only (orchestrator + shared classifications) + const orchestratorTools = await buildToolConfig({ + ...buildOptions, + classificationFilter: ["orchestrator", "shared"], + }); + + // Coding subagent receives execution tools (subagent + shared classifications) + const subagentTools = await buildToolConfig({ + ...buildOptions, + classificationFilter: ["subagent", "shared"], }); const coreBackend = createCoreBackend(); @@ -73,13 +112,17 @@ export async function createDeepAgentsOrchestrator(checkpointer = null) { const contextRoute = "/" + config.memory.contextDir.replace(/^\.?\//, ""); + // Filter skill paths by agent type + const orchestratorSkills = filterSkillPaths(skillPaths, ["orchestrator", "shared"]); + // Note: subagents receive all skills (skillPaths) — add to createSubAgent when API supports it + const codingSubAgent = createSubAgent({ name: "coding-agent", description: "Specialized agent for code-related tasks including file editing, debugging, implementation, and code review.", systemPrompt: codeAgentPrompt || "You are a coding specialist. Handle all code-related tasks.", model, - tools, + tools: subagentTools, middleware: [ todoListMiddleware(), createFilesystemMiddleware({ backend: coreBackend }), @@ -91,7 +134,7 @@ export async function createDeepAgentsOrchestrator(checkpointer = null) { return createDeepAgent({ model, - tools, + tools: orchestratorTools, systemPrompt, store: new InMemoryStore(), backend: new CompositeBackend(coreBackend, { @@ -99,7 +142,7 @@ export async function createDeepAgentsOrchestrator(checkpointer = null) { }), subagents: [codingSubAgent], ...(agentsPath && { memory: [agentsPath] }), - ...(skillPaths.length > 0 && { skills: skillPaths }), + ...(orchestratorSkills.length > 0 && { skills: orchestratorSkills }), ...(checkpointer && { checkpointer }), }); } diff --git a/src/tools/index.js b/src/tools/index.js index 3c84da2..f4e69f5 100644 --- a/src/tools/index.js +++ b/src/tools/index.js @@ -57,6 +57,31 @@ const TOOL_FACTORIES = { scanAgents: createScanAgentsTool, }; +/** + * Maps tool names to their agent type classification. + * - `orchestrator`: Tools the orchestrator uses for coordination (delegation, routing, synthesis) + * - `subagent`: Tools subagents use for execution (code editing, terminal, file operations) + * - `shared`: Tools both orchestrator and subagents may need + */ +export const TOOL_CLASSIFICATIONS = { + terminal: "subagent", // Execution: terminal access for subagents + process: "subagent", // Execution: process management for subagents + todo: "subagent", // Execution: task management for subagents + sessionSearch: "orchestrator", // Coordination: orchestrator searches past sessions for context + clarify: "shared", // Both: may need to clarify with user + webSearch: "shared", // Both: may need to search the web + webExtract: "shared", // Both: may need to extract web content + visionAnalyze: "shared", // Both: may need to analyze images + imageGenerate: "subagent", // Execution: image generation for subagents + executeCode: "subagent", // Execution: code execution for subagents + cronJob: "subagent", // Execution: scheduling for subagents + textToSpeech: "subagent", // Execution: TTS for subagents + mixtureOfAgents: "orchestrator", // Coordination: MOA for orchestrator decision-making + sampling: "orchestrator", // Coordination: memory sampling for orchestrator + date: "shared", // Both: may need date/time info + scanAgents: "orchestrator", // Coordination: scanning for AGENTS.md files +}; + /** * Build an array of LangChain tools gated by sandbox permissions and API keys. * Each tool is created with runtime options captured in a closure, ensuring @@ -73,6 +98,7 @@ const TOOL_FACTORIES = { * @param {string} [options.contextDir] - Directory for memory entries * @param {number} [options.ephemeralTtlDays] - TTL for ephemeral memories * @param {number} [options.ephemeralMaxEntries] - Max concurrent ephemeral entries + * @param {string[]} [options.classificationFilter] - Filter tools by classification (e.g., ['orchestrator', 'shared']). When omitted, all tools are included. * @param {object} [options.config] - Resolved config object from loadConfig() * @param {object} [options.config.providers] - Provider configs (openai, openrouter, fal) * @param {object} [options.config.search] - Search backend configs @@ -91,6 +117,7 @@ export async function buildToolConfig(options) { contextDir = "memory/context/", ephemeralTtlDays = 7, ephemeralMaxEntries = 10, + classificationFilter, config, } = options; @@ -208,5 +235,18 @@ export async function buildToolConfig(options) { } } + // Filter by classification if a filter is provided + if (classificationFilter && classificationFilter.length > 0) { + const filterSet = new Set(classificationFilter); + const filteredTools = []; + for (const tool of tools) { + const classification = TOOL_CLASSIFICATIONS[tool.name]; + if (classification && filterSet.has(classification)) { + filteredTools.push(tool); + } + } + return filteredTools; + } + return tools; } From 500919b7a7443cf0dac3746a7a5f6e3b978115a1 Mon Sep 17 00:00:00 2001 From: Jason Mulligan Date: Thu, 2 Jul 2026 21:13:15 -0400 Subject: [PATCH 03/10] feat: classify and assign tools/skills to orchestrator vs subagents --- .../.openspec.yaml | 0 .../design.md | 0 .../proposal.md | 0 .../specs/agent-tool-assignment/spec.md | 0 .../specs/tool-classification/spec.md | 0 .../tasks.md | 0 openspec/specs/agent-tool-assignment/spec.md | 37 +++++++++++ openspec/specs/tool-classification/spec.md | 63 +++++++++++++++++++ 8 files changed, 100 insertions(+) rename openspec/changes/{classify-assign-tools-skills-orchestrator-subagents => archive/2026-07-03-classify-assign-tools-skills-orchestrator-subagents}/.openspec.yaml (100%) rename openspec/changes/{classify-assign-tools-skills-orchestrator-subagents => archive/2026-07-03-classify-assign-tools-skills-orchestrator-subagents}/design.md (100%) rename openspec/changes/{classify-assign-tools-skills-orchestrator-subagents => archive/2026-07-03-classify-assign-tools-skills-orchestrator-subagents}/proposal.md (100%) rename openspec/changes/{classify-assign-tools-skills-orchestrator-subagents => archive/2026-07-03-classify-assign-tools-skills-orchestrator-subagents}/specs/agent-tool-assignment/spec.md (100%) rename openspec/changes/{classify-assign-tools-skills-orchestrator-subagents => archive/2026-07-03-classify-assign-tools-skills-orchestrator-subagents}/specs/tool-classification/spec.md (100%) rename openspec/changes/{classify-assign-tools-skills-orchestrator-subagents => archive/2026-07-03-classify-assign-tools-skills-orchestrator-subagents}/tasks.md (100%) create mode 100644 openspec/specs/agent-tool-assignment/spec.md create mode 100644 openspec/specs/tool-classification/spec.md diff --git a/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/.openspec.yaml b/openspec/changes/archive/2026-07-03-classify-assign-tools-skills-orchestrator-subagents/.openspec.yaml similarity index 100% rename from openspec/changes/classify-assign-tools-skills-orchestrator-subagents/.openspec.yaml rename to openspec/changes/archive/2026-07-03-classify-assign-tools-skills-orchestrator-subagents/.openspec.yaml diff --git a/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/design.md b/openspec/changes/archive/2026-07-03-classify-assign-tools-skills-orchestrator-subagents/design.md similarity index 100% rename from openspec/changes/classify-assign-tools-skills-orchestrator-subagents/design.md rename to openspec/changes/archive/2026-07-03-classify-assign-tools-skills-orchestrator-subagents/design.md diff --git a/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/proposal.md b/openspec/changes/archive/2026-07-03-classify-assign-tools-skills-orchestrator-subagents/proposal.md similarity index 100% rename from openspec/changes/classify-assign-tools-skills-orchestrator-subagents/proposal.md rename to openspec/changes/archive/2026-07-03-classify-assign-tools-skills-orchestrator-subagents/proposal.md diff --git a/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/specs/agent-tool-assignment/spec.md b/openspec/changes/archive/2026-07-03-classify-assign-tools-skills-orchestrator-subagents/specs/agent-tool-assignment/spec.md similarity index 100% rename from openspec/changes/classify-assign-tools-skills-orchestrator-subagents/specs/agent-tool-assignment/spec.md rename to openspec/changes/archive/2026-07-03-classify-assign-tools-skills-orchestrator-subagents/specs/agent-tool-assignment/spec.md diff --git a/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/specs/tool-classification/spec.md b/openspec/changes/archive/2026-07-03-classify-assign-tools-skills-orchestrator-subagents/specs/tool-classification/spec.md similarity index 100% rename from openspec/changes/classify-assign-tools-skills-orchestrator-subagents/specs/tool-classification/spec.md rename to openspec/changes/archive/2026-07-03-classify-assign-tools-skills-orchestrator-subagents/specs/tool-classification/spec.md diff --git a/openspec/changes/classify-assign-tools-skills-orchestrator-subagents/tasks.md b/openspec/changes/archive/2026-07-03-classify-assign-tools-skills-orchestrator-subagents/tasks.md similarity index 100% rename from openspec/changes/classify-assign-tools-skills-orchestrator-subagents/tasks.md rename to openspec/changes/archive/2026-07-03-classify-assign-tools-skills-orchestrator-subagents/tasks.md diff --git a/openspec/specs/agent-tool-assignment/spec.md b/openspec/specs/agent-tool-assignment/spec.md new file mode 100644 index 0000000..aeae235 --- /dev/null +++ b/openspec/specs/agent-tool-assignment/spec.md @@ -0,0 +1,37 @@ +# agent-tool-assignment Specification + +## Purpose +TBD - created by archiving change classify-assign-tools-skills-orchestrator-subagents. Update Purpose after archive. +## Requirements +### Requirement: Orchestrator SHALL have minimal tool set for coordination +The orchestrator agent SHALL only receive tools necessary for its coordination role: delegation, routing, and synthesis. It SHALL NOT receive execution tools (terminal, code editing, file operations). + +#### Scenario: Orchestrator lacks execution tools +- **WHEN** the orchestrator is created +- **THEN** tools like `terminal`, `process`, `executeCode`, and `todo` are NOT available to the orchestrator + +#### Scenario: Orchestrator has coordination tools +- **WHEN** the orchestrator is created +- **THEN** tools like `clarify`, `sessionSearch`, and `scanAgents` are available to the orchestrator + +### Requirement: Subagents SHALL have execution tools for task completion +Subagent agents SHALL receive tools necessary for their execution role: file operations, code editing, terminal access, and task management. + +#### Scenario: Coding subagent has execution tools +- **WHEN** the coding subagent is created +- **THEN** tools like `terminal`, `process`, `todo`, `executeCode`, and `web` tools are available + +### Requirement: Shared tools SHALL be available to both agents +Tools classified as `shared` SHALL be available to both the orchestrator and subagents. + +#### Scenario: Shared tool availability +- **WHEN** a tool is classified as `shared` +- **THEN** it is available to both the orchestrator and all subagents + +### Requirement: Tool assignment SHALL be configurable per agent type +The tool assignment system SHALL support adding new agent types with custom tool sets without modifying the core classification logic. + +#### Scenario: Adding a new agent type +- **WHEN** a new subagent type is added to `deepAgents.js` +- **THEN** it can receive a custom tool set by specifying the appropriate classification filter + diff --git a/openspec/specs/tool-classification/spec.md b/openspec/specs/tool-classification/spec.md new file mode 100644 index 0000000..6a298e8 --- /dev/null +++ b/openspec/specs/tool-classification/spec.md @@ -0,0 +1,63 @@ +# tool-classification Specification + +## Purpose +TBD - created by archiving change classify-assign-tools-skills-orchestrator-subagents. Update Purpose after archive. +## Requirements +### Requirement: Tools SHALL be classified by agent type +Each tool in `src/tools/index.js` SHALL have a classification indicating which agent type(s) may use it. Classifications are: `orchestrator`, `subagent`, or `shared`. + +#### Scenario: Classification map exists +- **WHEN** `src/tools/index.js` is loaded +- **THEN** a `TOOL_CLASSIFICATIONS` map exists mapping each tool name to one of: `orchestrator`, `subagent`, or `shared` + +#### Scenario: All tools have a classification +- **WHEN** all tools are defined in `TOOL_FACTORIES` +- **THEN** every tool name has a corresponding entry in `TOOL_CLASSIFICATIONS` + +### Requirement: `buildToolConfig()` SHALL support classification filtering +The `buildToolConfig()` function SHALL accept an optional `classificationFilter` parameter that filters tools by their classification. + +#### Scenario: No filter returns all tools +- **WHEN** `buildToolConfig()` is called without `classificationFilter` +- **THEN** all tools that pass permission checks are included (current behavior) + +#### Scenario: Filter with orchestrator classification +- **WHEN** `buildToolConfig()` is called with `classificationFilter: ['orchestrator', 'shared']` +- **THEN** only tools classified as `orchestrator` or `shared` are included + +#### Scenario: Filter with subagent classification +- **WHEN** `buildToolConfig()` is called with `classificationFilter: ['subagent', 'shared']` +- **THEN** only tools classified as `subagent` or `shared` are included + +### Requirement: Orchestrator SHALL receive only orchestrator-classified and shared tools +The orchestrator agent in `deepAgents.js` SHALL receive a filtered tool set containing only tools classified as `orchestrator` or `shared`. + +#### Scenario: Orchestrator tool assignment +- **WHEN** `createDeepAgentsOrchestrator()` creates the orchestrator +- **THEN** the orchestrator receives tools filtered by `['orchestrator', 'shared']` + +### Requirement: Subagents SHALL receive subagent-classified and shared tools +Subagent agents in `deepAgents.js` SHALL receive a filtered tool set containing only tools classified as `subagent` or `shared`. + +#### Scenario: Coding subagent tool assignment +- **WHEN** `createDeepAgentsOrchestrator()` creates the coding subagent +- **THEN** the coding subagent receives tools filtered by `['subagent', 'shared']` + +### Requirement: Skills SHALL be classified by agent type +Skills SHALL be classified into categories: `orchestrator`, `subagent`, or `shared`. The orchestrator SHALL receive only orchestrator-classified and shared skills. Subagents SHALL receive all skills (subagent and shared). + +#### Scenario: Skill path filtering for orchestrator +- **WHEN** `createDeepAgentsOrchestrator()` assigns skills to the orchestrator +- **THEN** only skills classified as `orchestrator` or `shared` are included + +#### Scenario: Skill path filtering for subagent +- **WHEN** `createDeepAgentsOrchestrator()` assigns skills to the coding subagent +- **THEN** all skills are included (subagent and shared) + +### Requirement: Classification SHALL be documented for new tools +When a new tool is added to `src/tools/index.js`, its classification SHALL be documented in the `TOOL_CLASSIFICATIONS` map and in code comments. + +#### Scenario: New tool requires classification +- **WHEN** a new tool is added to `TOOL_FACTORIES` +- **THEN** a corresponding entry MUST be added to `TOOL_CLASSIFICATIONS` with a clear rationale + From 039fdd9b7ac2d76c4b5e1c347781531833a50491 Mon Sep 17 00:00:00 2001 From: Jason Mulligan Date: Thu, 2 Jul 2026 22:35:17 -0400 Subject: [PATCH 04/10] WIP --- src/agent/deepAgents.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/agent/deepAgents.js b/src/agent/deepAgents.js index 7e909f5..cb63ab8 100644 --- a/src/agent/deepAgents.js +++ b/src/agent/deepAgents.js @@ -2,6 +2,7 @@ import { createDeepAgent, CompositeBackend, createSubAgent, + createSubAgentMiddleware, createFilesystemMiddleware, createMemoryMiddleware, createSummarizationMiddleware, @@ -141,6 +142,7 @@ export async function createDeepAgentsOrchestrator(checkpointer = null) { [contextRoute]: contextBackend, }), subagents: [codingSubAgent], + middleware: [createSubAgentMiddleware({ subagents: [codingSubAgent] })], ...(agentsPath && { memory: [agentsPath] }), ...(orchestratorSkills.length > 0 && { skills: orchestratorSkills }), ...(checkpointer && { checkpointer }), From 9fae9b59e3b824c339d7d72238dc56d87b601a53 Mon Sep 17 00:00:00 2001 From: Jason Mulligan Date: Fri, 3 Jul 2026 09:06:13 -0400 Subject: [PATCH 05/10] WIP --- src/agent/deepAgents.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/agent/deepAgents.js b/src/agent/deepAgents.js index cb63ab8..b85d523 100644 --- a/src/agent/deepAgents.js +++ b/src/agent/deepAgents.js @@ -142,7 +142,6 @@ export async function createDeepAgentsOrchestrator(checkpointer = null) { [contextRoute]: contextBackend, }), subagents: [codingSubAgent], - middleware: [createSubAgentMiddleware({ subagents: [codingSubAgent] })], ...(agentsPath && { memory: [agentsPath] }), ...(orchestratorSkills.length > 0 && { skills: orchestratorSkills }), ...(checkpointer && { checkpointer }), From 36727532d105373fd4d27d81ca0dd4cd20418bec Mon Sep 17 00:00:00 2001 From: Jason Mulligan Date: Fri, 3 Jul 2026 09:08:09 -0400 Subject: [PATCH 06/10] fix: remove unused createSubAgentMiddleware import and apply formatting --- src/agent/deepAgents.js | 1 - src/tui/app.js | 14 ++++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/agent/deepAgents.js b/src/agent/deepAgents.js index b85d523..7e909f5 100644 --- a/src/agent/deepAgents.js +++ b/src/agent/deepAgents.js @@ -2,7 +2,6 @@ import { createDeepAgent, CompositeBackend, createSubAgent, - createSubAgentMiddleware, createFilesystemMiddleware, createMemoryMiddleware, createSummarizationMiddleware, diff --git a/src/tui/app.js b/src/tui/app.js index e9ff673..b030f99 100644 --- a/src/tui/app.js +++ b/src/tui/app.js @@ -330,7 +330,12 @@ export default function App({ if (shouldAbort()) return; - finalizeStreaming(responseContent, committedReasoning, lastToolCallDisplay, todoStatusLines); + finalizeStreaming( + responseContent, + committedReasoning, + lastToolCallDisplay, + todoStatusLines, + ); // Persist assistant response to session state if (sessionState) { @@ -798,7 +803,12 @@ export default function App({ * @param {string} lastToolCallDisplay - Tool call display text * @param {string} todoStatusLines - Todo status lines */ - const finalizeStreaming = (responseContent, committedReasoning, lastToolCallDisplay, todoStatusLines) => { + const finalizeStreaming = ( + responseContent, + committedReasoning, + lastToolCallDisplay, + todoStatusLines, + ) => { setMessages((prev) => { const cloned = [...prev]; const last = cloned[cloned.length - 1]; From 6aa589fa26f8408fade2be4a5105164bc290e6e8 Mon Sep 17 00:00:00 2001 From: Jason Mulligan Date: Fri, 3 Jul 2026 09:22:28 -0400 Subject: [PATCH 07/10] fix: pass coding-agent spec directly to createDeepAgent to preserve name --- src/agent/deepAgents.js | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/agent/deepAgents.js b/src/agent/deepAgents.js index 7e909f5..bda4faa 100644 --- a/src/agent/deepAgents.js +++ b/src/agent/deepAgents.js @@ -1,7 +1,6 @@ import { createDeepAgent, CompositeBackend, - createSubAgent, createFilesystemMiddleware, createMemoryMiddleware, createSummarizationMiddleware, @@ -116,22 +115,6 @@ export async function createDeepAgentsOrchestrator(checkpointer = null) { const orchestratorSkills = filterSkillPaths(skillPaths, ["orchestrator", "shared"]); // Note: subagents receive all skills (skillPaths) — add to createSubAgent when API supports it - const codingSubAgent = createSubAgent({ - name: "coding-agent", - description: - "Specialized agent for code-related tasks including file editing, debugging, implementation, and code review.", - systemPrompt: codeAgentPrompt || "You are a coding specialist. Handle all code-related tasks.", - model, - tools: subagentTools, - middleware: [ - todoListMiddleware(), - createFilesystemMiddleware({ backend: coreBackend }), - createSummarizationMiddleware({ backend: subAgentsBackend }), - createPatchToolCallsMiddleware(), - createMemoryMiddleware({ backend: subAgentsBackend }), - ], - }); - return createDeepAgent({ model, tools: orchestratorTools, @@ -140,7 +123,23 @@ export async function createDeepAgentsOrchestrator(checkpointer = null) { backend: new CompositeBackend(coreBackend, { [contextRoute]: contextBackend, }), - subagents: [codingSubAgent], + subagents: [ + { + name: "coding-agent", + description: + "Specialized agent for code-related tasks including file editing, debugging, implementation, and code review.", + systemPrompt: codeAgentPrompt || "You are a coding specialist. Handle all code-related tasks.", + model, + tools: subagentTools, + middleware: [ + todoListMiddleware(), + createFilesystemMiddleware({ backend: coreBackend }), + createSummarizationMiddleware({ backend: subAgentsBackend }), + createPatchToolCallsMiddleware(), + createMemoryMiddleware({ backend: subAgentsBackend }), + ], + }, + ], ...(agentsPath && { memory: [agentsPath] }), ...(orchestratorSkills.length > 0 && { skills: orchestratorSkills }), ...(checkpointer && { checkpointer }), From f94f18834160fe8ff7984ca47caca5c21017cec5 Mon Sep 17 00:00:00 2001 From: Jason Mulligan Date: Fri, 3 Jul 2026 09:27:56 -0400 Subject: [PATCH 08/10] fix: update deepAgents.js for skill classification --- src/agent/deepAgents.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/agent/deepAgents.js b/src/agent/deepAgents.js index bda4faa..514ad6e 100644 --- a/src/agent/deepAgents.js +++ b/src/agent/deepAgents.js @@ -130,14 +130,7 @@ export async function createDeepAgentsOrchestrator(checkpointer = null) { "Specialized agent for code-related tasks including file editing, debugging, implementation, and code review.", systemPrompt: codeAgentPrompt || "You are a coding specialist. Handle all code-related tasks.", model, - tools: subagentTools, - middleware: [ - todoListMiddleware(), - createFilesystemMiddleware({ backend: coreBackend }), - createSummarizationMiddleware({ backend: subAgentsBackend }), - createPatchToolCallsMiddleware(), - createMemoryMiddleware({ backend: subAgentsBackend }), - ], + tools: subagentTools }, ], ...(agentsPath && { memory: [agentsPath] }), From 8fe44a1d18df1d002cd40bfaa0c1fd37c0d848af Mon Sep 17 00:00:00 2001 From: Jason Mulligan Date: Fri, 3 Jul 2026 09:31:31 -0400 Subject: [PATCH 09/10] fix: remove unused imports and duplicate code from deepAgents.js --- src/agent/deepAgents.js | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/agent/deepAgents.js b/src/agent/deepAgents.js index 514ad6e..35dccbc 100644 --- a/src/agent/deepAgents.js +++ b/src/agent/deepAgents.js @@ -1,12 +1,4 @@ -import { - createDeepAgent, - CompositeBackend, - createFilesystemMiddleware, - createMemoryMiddleware, - createSummarizationMiddleware, - createPatchToolCallsMiddleware, -} from "deepagents"; -import { todoListMiddleware } from "langchain"; +import { createDeepAgent, CompositeBackend } from "deepagents"; import { readFileSync } from "node:fs"; import { join } from "node:path"; import { InMemoryStore } from "@langchain/langgraph-checkpoint"; @@ -17,8 +9,6 @@ import { createChatModel } from "../provider/openai.js"; import { buildToolConfig } from "../tools/index.js"; import { createCoreBackend } from "./coreBackend.js"; import { createContextBackend } from "./contextBackend.js"; -import { createSubAgentsBackend } from "./subAgentsBackend.js"; - // Skill classification map — classifies each skill by agent type. // Skills are discovered dynamically; this map provides the classification // for filtering. Initially, all skills are classified as "subagent" since @@ -107,7 +97,6 @@ export async function createDeepAgentsOrchestrator(checkpointer = null) { const coreBackend = createCoreBackend(); const contextBackend = createContextBackend(); - const subAgentsBackend = createSubAgentsBackend(); const contextRoute = "/" + config.memory.contextDir.replace(/^\.?\//, ""); From f65a0ee612f09e929fffa882cd7c0c4420e3b9f5 Mon Sep 17 00:00:00 2001 From: Jason Mulligan Date: Fri, 3 Jul 2026 09:36:43 -0400 Subject: [PATCH 10/10] docs: add task tool examples to TUTORIAL.md --- docs/TUTORIAL.md | 73 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/docs/TUTORIAL.md b/docs/TUTORIAL.md index 94b4e28..cc99c11 100644 --- a/docs/TUTORIAL.md +++ b/docs/TUTORIAL.md @@ -327,6 +327,79 @@ This mode is used by internal cron jobs and NPM installations. --- +## 🤖 Automating Coding Tasks with the Task Tool + +`madz` can delegate complex, multi-step coding tasks to specialized subagents through the `task` tool. Instead of you orchestrating each step manually — checking git status, running lint, editing files, committing — you describe the outcome you want and a subagent handles the execution. The machine does not wait for idle terminals; it waits for clear instructions. + +### Available Agent Types + +Two agent types are available, each with a distinct scope: + +- **`general-purpose`** — Research, file searches, multi-step tasks that span multiple domains. Has access to all tools. Use this when the task is exploratory, involves gathering information, or doesn't fit neatly into a single specialty. + +- **`coding-agent`** — Specialized for code-related work: file editing, debugging, implementation, code review, and git operations. This agent understands project conventions, follows linting standards, and respects commit message formatting rules. Use this when the task touches source code, tests, or version control. + +### Concrete Examples + +**Example 1: Commit and Push** + +``` +task coding-agent: commit and push to this branch, we have an open pr +``` + +The coding-agent checks git status, stages changed files, crafts a descriptive commit message following the project's conventional commit format, and pushes to the remote branch. It will not push without explicit approval — see the notes below. + +**Example 2: Run Lint, Fix Errors, Commit, and Push** + +``` +task coding-agent: run lint, fix any errors, then commit and push +``` + +The coding-agent runs the project's lint command, identifies each issue, applies fixes to the relevant files, re-runs lint to verify all issues are resolved, and then proceeds to commit and push. If a fix is ambiguous or risky, the agent will pause and ask for guidance rather than guessing. + +**Example 3: Update a PR** + +``` +task coding-agent: update PR #123 with the latest changes from this branch +``` + +The coding-agent can interact with GitHub pull requests — updating PR descriptions, adding review comments, requesting changes, or merging. It reads the current branch state, diffs against the target branch, and composes meaningful descriptions from the actual code changes. + +**Example 4: Create an Issue** + +``` +task coding-agent: create an issue for memory leak in session manager +``` + +The coding-agent can create GitHub issues with proper titles, descriptions, labels, and categorization. It will search the codebase for relevant context, reference related files, and suggest labels based on the project's issue taxonomy. + +**Example 5: Debug a Failing Test** + +``` +task coding-agent: debug the failing test in tests/unit/skills.test.js and fix it +``` + +The coding-agent runs the specified test, analyzes the failure output, traces the root cause through the relevant source files, and applies a fix. It re-runs the test to confirm the fix resolves the issue and does not introduce regressions in related tests. + +### Best Practices + +- **Be specific in your delegation.** Clear, unambiguous instructions produce better results. "Fix the lint errors" is good; "run eslint on src/ and fix all errors without changing the public API" is better. +- **The coding-agent operates in the project's CWD by default.** All file paths and commands are resolved relative to the working directory. +- **It follows project conventions.** The agent reads `AGENTS.md` rules, respects the project's commit message format, and adheres to linting and formatting standards. +- **For git operations, it respects branch protection.** It will not force-push or bypass protected branches. +- **Complex tasks benefit from step-by-step instructions.** If a task has multiple phases, describe them in order and the agent will execute sequentially. + +### Important Notes + +- The coding-agent **never rebases** without explicit agreement. +- It **never pushes** without explicit user approval. +- It **never changes branches** without permission. +- It follows the project's **conventional commit format** for all commits. + +These guardrails exist so you can delegate with confidence. The agent is a collaborator, not an autonomous actor. It acts, but it does not overreach. + +--- + ## 🔧 Troubleshooting ### Docker-Specific