Skip to content

feat: allow custom subagents to delegate tasks via task()#1908

Open
Stranmor wants to merge 3 commits intocode-yeongyu:devfrom
Stranmor:feat/configurable-subagent-task-access
Open

feat: allow custom subagents to delegate tasks via task()#1908
Stranmor wants to merge 3 commits intocode-yeongyu:devfrom
Stranmor:feat/configurable-subagent-task-access

Conversation

@Stranmor
Copy link

@Stranmor Stranmor commented Feb 16, 2026

Summary

Custom subagents defined in oh-my-opencode.json cannot use task() to delegate work to other agents. This PR fixes three independent issues that collectively prevent the pipeline from working.

Problem

When a user defines custom agents (e.g., critic, breaker, type-sentinel) in oh-my-opencode.json, those agents:

  1. Cannot call task()buildSubagentTools() hardcodes task: false for background tasks and only allows task for plan-family agents in sync flows
  2. Are never registered with opencodeapplyAgentConfig() passes custom agents as overrides to createBuiltinAgents(), which only processes known builtin names
  3. Are blocked by global permission denyapplyToolConfig() sets config.permission.task = "deny" globally, then only whitelists hardcoded agents

Changes

Commit 1 (agent-tool-restrictions.ts): Check AGENT_RESTRICTIONS instead of hardcoding task: false. 4 code paths fixed.

Commit 2 (agent-config-handler.ts, tool-config-handler.ts): Register custom agents from config. Grant task: "allow" to non-restricted agents.

Replace hardcoded `task: false` in all subagent spawning paths with
`buildSubagentTools()` — a centralized function that respects
AGENT_RESTRICTIONS.

Built-in agents (explore, librarian, oracle, metis, momus,
sisyphus-junior) keep `task: false` via their AGENT_RESTRICTIONS entries.
Custom/user-defined agents (not in AGENT_RESTRICTIONS) now get
`task: true`, enabling multi-level agent delegation (e.g. a critic
agent spawning a breaker agent).

This unblocks workflows where specialized review agents need to
orchestrate sub-pipelines without routing through the top-level
orchestrator.
Copy link

@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.

1 issue found across 11 files

Confidence score: 2/5

  • Potential deadlock in src/features/background-agent/spawner.ts when nested agents share a low-limit concurrency key and both try to acquire it, which can block parent/child execution
  • Severity is high (8/10) with plausible user-facing hangs, so merge risk is elevated despite being a single issue
  • Pay close attention to src/features/background-agent/spawner.ts - nested concurrency acquisition can stall agents
Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/features/background-agent/spawner.ts">

<violation number="1" location="src/features/background-agent/spawner.ts:143">
P1: Potential deadlock when nested agents share concurrency key with low limits. Parent acquires slot and invokes task tool (now enabled), child attempts to acquire same key but blocks because parent holds it while waiting for child completion.</violation>
</file>

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

call_omo_agent: true,
question: false,
},
tools: buildSubagentTools(input.agent),
Copy link

@cubic-dev-ai cubic-dev-ai bot Feb 16, 2026

Choose a reason for hiding this comment

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

P1: Potential deadlock when nested agents share concurrency key with low limits. Parent acquires slot and invokes task tool (now enabled), child attempts to acquire same key but blocks because parent holds it while waiting for child completion.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/features/background-agent/spawner.ts, line 143:

<comment>Potential deadlock when nested agents share concurrency key with low limits. Parent acquires slot and invokes task tool (now enabled), child attempts to acquire same key but blocks because parent holds it while waiting for child completion.</comment>

<file context>
@@ -140,12 +140,7 @@ export async function startTask(
-        call_omo_agent: true,
-        question: false,
-      },
+      tools: buildSubagentTools(input.agent),
       parts: [{ type: "text", text: input.prompt }],
     },
</file context>
Fix with Cubic

Custom agents defined in oh-my-opencode.json (e.g. breaker, type-sentinel)
were silently dropped because they were passed as overrides to
createBuiltinAgents() which only processes known builtin names.

Additionally, the global config.permission.task = 'deny' blocked custom
agents from calling task() since they were never whitelisted.

Changes:
- applyAgentConfig: add custom agents from pluginConfig.agents that aren't
  already registered (both sisyphus-enabled and disabled paths)
- applyToolConfig: grant task='allow' to all agents not explicitly blocked
  by AGENT_RESTRICTIONS
AgentOverridesSchema used strict z.object() with only hardcoded builtin
agent names. Zod strips unknown keys during safeParse, silently dropping
any custom agents (breaker, critic, type-sentinel, etc.) from the parsed
config.

Adding .catchall(AgentOverrideConfigSchema) preserves unknown agent keys
while still validating them against the same schema.
@sisyphus-dev-ai
Copy link
Collaborator

@Stranmor Thanks for the PR! There are a couple of items to address before we can merge:

  1. Merge conflicts: This branch currently has conflicts that need to be resolved.

  2. Cubic review feedback: The AI reviewer identified a potential deadlock issue in src/features/background-agent/spawner.ts around line 143. The concern is about nested agents sharing a concurrency key with low limits - when a parent acquires a slot and invokes the task tool, a child attempting to acquire the same key could block because the parent holds it while waiting for child completion.

Could you take a look at these issues? Once the conflicts are resolved and the deadlock concern is addressed (or explained if it is not a real issue), we can proceed with the review.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments