Skip to content

Conversation

@uinstinct
Copy link
Contributor

@uinstinct uinstinct commented Dec 11, 2025

Description

This PR introduces isolated sub agents to work on specialized tasks.

  • Currently when subagent runs, all tool permissions are set to allow for the subagent
  • Introduces another role to the model called subagent

Invoke the cli using ./dist/cn.js --verbose --beta-subagent-tool as it is behind a beta flag

Example explorer subagent

  - name: explorer
    provider: anthropic
    model: claude-haiku-4-5
    apiKey: <api-key>
    chatOptions:
      baseSystemMessage: |
        You are a file search specialist. You specialize at navigating and exploring codebases.

        Guidelines:
        - You can skip explain your thought process
        - In your final response, use absolute file paths
        - Do not create any files, or run bash commands that modify the user's system state in any way

        Complete the given search request efficiently and report your findings clearly.

closes CON-5135

AI Code Review

  • Team members only: AI review runs automatically when PR is opened or marked ready for review
  • Team members can also trigger a review by commenting @continue-review

Checklist

  • [] I've read the contributing guide
  • [] The relevant docs, if any, have been updated or created
  • [] The relevant tests, if any, have been updated or created

Screen recording or screenshot

[ When applicable, please include a short screen recording or screenshot - this makes it much easier for us as contributors to review and understand your changes. See this PR as a good example. ]

Tests

[ What tests were added or updated to ensure the changes work as expected? ]


Summary by cubic

Introduce subagents to the CLI. You can now spawn a specialized agent via the Subagent tool to handle multi-step tasks autonomously with live streaming output.

  • New Features

    • Added Subagent tool with parameters: description, prompt, subagent_name.
    • Agents are loaded from assistant config; selects models with role "subagent" and a base system message.
    • Executor runs subagents in a child session, isolates system message, and temporarily disables chat history interference.
    • Allows all tools inside subagents for now.
    • Streams tool call output using toolCallId; UI shows live subagent output and truncates long logs.
    • Added task metadata footer with status.
    • Subagent tool is behind a beta flag; enable with --beta-subagent-tool.
    • Press Escape to cancel a running subagent; the child session is aborted.
  • Migration

    • Tool.run now supports an optional second parameter: context?: { toolCallId: string }.
      • If your TypeScript settings are strict, update custom tools to match the new signature:
        • Before: run(args) => Promise
        • After: run(args, context?) => Promise

Written for commit c2d928d. Summary will update on new commits.

@continue
Copy link
Contributor

continue bot commented Dec 11, 2025

All Green - Keep your PRs mergeable

Learn more

All Green is an AI agent that automatically:

✅ Addresses code review comments

✅ Fixes failing CI checks

✅ Resolves merge conflicts

continue bot added a commit that referenced this pull request Dec 11, 2025
Add comprehensive documentation for the new Subagent feature including:
- Architecture overview and execution flow
- Built-in agents (general agent)
- When to use subagents
- Tool interface and parameters
- Output streaming behavior
- Implementation details and migration notes
- Error handling
- Future enhancements

Also update AGENTS.md to reference the new subagents documentation.

This documentation is for PR #9128.

Generated with [Continue](https://continue.dev)

Co-Authored-By: Continue <[email protected]>
Co-authored-by: nate <[email protected]>
@continue
Copy link
Contributor

continue bot commented Dec 11, 2025

📚 Documentation PR created!

I've reviewed the changes in this PR and created PR #9129 with comprehensive documentation for the Subagent feature.

The documentation includes:

  • Architecture overview and execution flow
  • Built-in agents (general agent)
  • When to use subagents vs. direct tool calls
  • Tool interface, parameters, and examples
  • Output streaming behavior
  • Implementation details and migration notes for custom tools
  • Error handling
  • Future enhancements

The docs are added to extensions/cli/docs/subagents.md and extensions/cli/AGENTS.md is updated to reference them, following the same structure and level of detail as existing CLI documentation like artifact-uploads.md and storage-sync.md.

Please review when you have a chance!

@continue
Copy link
Contributor

continue bot commented Dec 11, 2025

📚 Documentation PR #9129 is ready for review

I've created comprehensive documentation for the Subagent feature. The PR is experiencing some transient CI failures (sqlite download 503 errors) that are unrelated to the documentation changes - all code quality checks (prettier, lint, core-checks, etc.) are passing.

The documentation covers:

  • Architecture overview and execution flow
  • Built-in agents (general agent)
  • When to use subagents vs. direct tool calls
  • Tool interface, parameters, and examples
  • Output streaming behavior
  • Implementation details and migration notes for custom tools
  • Error handling
  • Future enhancements

Feel free to review the docs while the CI infrastructure issues resolve themselves!

@continue
Copy link
Contributor

continue bot commented Dec 15, 2025

🤖 All Green agent started: View agent

continue bot and others added 11 commits December 15, 2025 03:50
Move services import to lazy evaluation inside the run function to avoid
circular dependency between ToolPermissionService -> allBuiltIns -> subagent -> services -> ToolPermissionService.

This fixes the 'ToolPermissionService is not a constructor' error in tests.

Co-authored-by: nate <[email protected]>
Move services import to lazy evaluation inside executeSubAgent function
to avoid circular dependency. Pass services as parameter to
buildAgentSystemMessage helper function.

Co-authored-by: nate <[email protected]>
Create builtInToolNames.ts with just the tool name constants to avoid
importing the actual tool implementations. This breaks the circular
dependency chain: ToolPermissionService -> allBuiltIns -> subagent ->
executor -> services -> ToolPermissionService.

Co-authored-by: nate <[email protected]>
Update BUILT_IN_TOOL_NAMES to match the actual tools in allBuiltIns.ts,
including UploadArtifact which was missing. Remove incorrect tool names
that don't exist.

Co-authored-by: nate <[email protected]>
Move BUILT_IN_TOOL_NAMES import to proper position according to eslint
import/order rules.

Co-authored-by: nate <[email protected]>
@uinstinct uinstinct marked this pull request as ready for review December 19, 2025 15:57
@uinstinct uinstinct requested a review from a team as a code owner December 19, 2025 15:57
@uinstinct uinstinct requested review from sestinj and removed request for a team December 19, 2025 15:57
@dosubot dosubot bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Dec 19, 2025
export const subagentTool: Tool = {
name: "Subagent",
displayName: "Subagent",
description: generateSubagentToolDescription(),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sestinj is there a way to lazily load tool description or load them after model service is initialized? (I am calling services.model inside that function but that returns any empty array for the models)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, not currently a way to do this. Do you think that there are enough differences between sub-agents and tools that we might want to make a separate abstraction, or just a different special "type" of tool for sub-agents? We might end up losing a lot of time by trying to force sug-agents into the tools UI

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

6 issues found across 13 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="extensions/cli/src/services/ModelService.ts">

<violation number="1" location="extensions/cli/src/services/ModelService.ts:318">
P1: Wrong property name: checking `baseSystemMessage` but subagents use `baseAgentSystemMessage` per the PR description config example. This will filter out valid subagent models.</violation>
</file>

<file name="core/config/yaml/loadYaml.ts">

<violation number="1" location="core/config/yaml/loadYaml.ts:190">
P1: Missing handler for the `subagent` role in the model loading loop. Models configured with `roles: [&quot;subagent&quot;]` will not be added to `modelsByRole.subagent` because there&#39;s no corresponding `if (model.roles?.includes(&quot;subagent&quot;))` block like the other roles have (lines 297-335).</violation>
</file>

<file name="extensions/cli/src/tools/subagent.ts">

<violation number="1" location="extensions/cli/src/tools/subagent.ts:45">
P2: Error message hardcodes &#39;general&#39; instead of using `getSubagentNames()` like the description does. This will show incorrect available agents to users.</violation>
</file>

<file name="extensions/cli/src/subagent/get-agents.ts">

<violation number="1" location="extensions/cli/src/subagent/get-agents.ts:22">
P1: Wrong property accessed: should use `baseAgentSystemMessage` instead of `baseSystemMessage`. The PR example shows subagents are configured with `baseAgentSystemMessage`, but this code reads `baseSystemMessage`, resulting in `undefined` being displayed in the tool description.</violation>
</file>

<file name="extensions/cli/src/subagent/executor.ts">

<violation number="1" location="extensions/cli/src/subagent/executor.ts:46">
P1: Property name mismatch: code reads `baseSystemMessage` but PR description shows config using `baseAgentSystemMessage`. This would cause the agent&#39;s custom system message to be ignored. Verify the correct property name and update accordingly.</violation>

<violation number="2" location="extensions/cli/src/subagent/executor.ts:82">
P1: State modifications (tool permissions, system message, chat history) occur before the inner try block that contains the cleanup in its finally clause. If an error occurs during setup (e.g., `buildAgentSystemMessage` throws), these modifications won&#39;t be restored. Consider moving all state modifications inside the inner try block, or restructuring to ensure cleanup always runs.</violation>
</file>

Reply to cubic to teach it or ask questions. Re-run a review with @cubic-dev-ai review this PR

Copy link
Collaborator

@RomneyDa RomneyDa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Could we add this tool under a --beta-subagent-tool flag? Then I would feel way more comfortable about just merging this to test
  • Let's make sure the subagent won't have the subagent tool, and I wonder if for now it shouldn't have any write tools either but write tools are probably fine
  • I think we should add some kind of timeout like 5 minutes to make sure it doesn't get stuck in limbo e.g. by running npm run dev or something
  • Let's add tests including e2e tests
  • Added some nitpick comments
  • Cubic feedback seems valid

}

// Lazy import services to avoid circular dependency
const { services } = await import("../services/index.js");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ideally rearrange to avoid this lazy import

Copy link
Contributor Author

@uinstinct uinstinct Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is becoming little too complicated. I tried it in 2 commits but tests would fail.
Without this a cyclical import happens for tests. The reason is streamChatResponse (used by subagent now) uses services which in turn uses ToolPermissions. To decouple services from ToolPermissions would require a lot of refactoring.

@github-project-automation github-project-automation bot moved this from Todo to In Progress in Issues and PRs Jan 6, 2026
@dosubot dosubot bot added size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Jan 7, 2026
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 39 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name=".github/workflows/continue-agents.yml">

<violation number="1">
P1: Script injection vulnerability: Agent output is directly interpolated into JavaScript template literals. If the output contains backticks or `${...}`, it will break the script or cause code injection. Use environment variables instead and access via `process.env`.</violation>
</file>

<file name=".github/workflows/runloop-blueprint-staging-template.json">

<violation number="1">
P2: Security: `curl | sudo bash` pattern downloads and executes untrusted code with root privileges. Consider downloading the script first and verifying its checksum, or use Infisical's package repository method with GPG key verification (similar to the GitHub CLI installation pattern used below).</violation>
</file>

<file name="extensions/cli/src/subagent/executor.ts">

<violation number="1" location="extensions/cli/src/subagent/executor.ts:129">
P1: Event listener added with `escapeEvents.on()` is never removed, causing a memory leak and potential stale closure issues. Each call to `executeSubAgent` adds a new listener that persists after the function completes. Store the handler and remove it in the `finally` block.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@dosubot dosubot bot added size:L This PR changes 100-499 lines, ignoring generated files. and removed size:XL This PR changes 500-999 lines, ignoring generated files. labels Jan 7, 2026
@dosubot dosubot bot added size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Jan 7, 2026
@uinstinct uinstinct changed the title [WIP] feat: subagents feat: subagents Jan 8, 2026
@uinstinct uinstinct requested a review from RomneyDa January 8, 2026 16:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

3 participants