Bug Report: task / parallel_task child runs drop agent permission configuration and safe-deny tool execution
Summary
Delegated child runs launched through the builtin task / parallel_task path do not inherit the selected agent's permission checker into the child AgentConfig.
As a result, child tool calls fall back to Ask, and when no confirmation manager is present they are safe-denied with a MissingConfirmationManager error even when the delegated agent definition already carries an explicit allow policy.
This was observed from an external host integration, but the controlling code path appears to be inside A3S Code core rather than in host-side worker registration.
Impact
- Custom worker agents with explicit allow-default or allow-list permissions cannot actually execute tools when invoked through task / parallel_task.
- Hosts can successfully register worker names and resolve them in task calls, but delegated child runs still fail at tool execution time.
- This makes task / parallel_task unreliable for integrations that depend on delegated read/write/bash capability without an interactive HITL loop.
Environment
- Repository: AI45Lab/Code
- Branch: main
- Observed from a Node host integration using the vendored Code SDK
- OS: Windows
Expected behavior
When a delegated agent definition already has an explicit permission policy, the child run created by task / parallel_task should inherit that policy into its child AgentConfig in the same way the normal agent binding path does.
If the delegated agent definition allows write, edit, bash, or other tools, the child run should be able to execute those tools without unexpectedly falling back to Ask.
Actual behavior
The delegated child run is created with a fresh AgentConfig built from defaults plus prompt/tools/max_tool_rounds only.
That default AgentConfig has:
- permission_checker: None
- permission_policy: None
- confirmation_manager: None
The safety gate then does this:
- No permission checker means permission_decision falls back to Ask.
- Ask without a confirmation manager becomes a safe deny.
The resulting runtime error is the MissingConfirmationManager-style denial:
Tool '' requires confirmation but no HITL confirmation manager is configured.
Why this looks like a core bug instead of a host configuration bug
The host can already supply worker definitions with explicit permissions.
The apparent gap is that the task child-run path does not carry those permissions into child AgentConfig, even though the normal session binding path already has logic for that.
Relevant code paths:
- Child task path manually builds AgentConfig in Code/core/src/tools/task.rs
- Normal agent-definition binding path applies permissions in Code/core/src/agent_api/agent_binding.rs
- AgentConfig defaults leave permission_checker and confirmation_manager empty in Code/core/src/agent.rs
- Safety gate falls back to Ask and then safe-denies without confirmation manager in Code/core/src/safety_gate.rs
Relevant source evidence
1. task child path manually builds a fresh AgentConfig
In Code/core/src/tools/task.rs, the child run is constructed with a manually assembled AgentConfig:
- prompt_slots
- tools
- max_tool_rounds
- then ..AgentConfig::default()
That means the child config does not receive the selected agent's permission_checker or confirmation_manager.
The same block only sets a deny-only guard policy on ToolExecutor:
- child_executor.set_guard_policy(...agent.permissions...)
That guard is not equivalent to populating child AgentConfig.permission_checker for the safety gate.
2. The normal binding path already knows how to apply permissions
In Code/core/src/agent_api/agent_binding.rs:
- apply_permissions sets opts.permission_checker = Some(Arc::new(def.permissions.clone())) when the agent definition has permissions.
So there is already a canonical path that propagates agent-definition permissions correctly.
3. AgentConfig defaults to no permission checker and no confirmation manager
In Code/core/src/agent.rs default AgentConfig:
- permission_checker: None
- permission_policy: None
- confirmation_manager: None
4. The safety gate explicitly turns that into Ask, then safe deny
In Code/core/src/safety_gate.rs:
- permission_decision uses the checker when present
- otherwise it falls back to PermissionDecision::Ask
- confirmation_decision denies when no confirmation manager exists
5. Existing tests already document this behavior
In Code/core/src/agent/tests.rs:
- Without a confirmation manager, Ask = safe deny.
So the current runtime behavior is internally consistent, but the task child-run path appears to be dropping the configuration needed to avoid Ask.
Minimal conceptual reproduction
- Register or resolve a delegated agent definition with explicit non-strict permissions, for example an allow-default or allow-list worker that can write files.
- Invoke that agent through task or parallel_task.
- Inside the child run, call a tool such as write.
- Observe that the child run behaves as if permission_checker is absent:
- permission falls back to Ask
- no confirmation manager exists in the child config
- tool execution is denied
Suggested fix
The child run created in Code/core/src/tools/task.rs should populate child AgentConfig using the same effective permission propagation model as the normal agent-binding path.
At minimum, the child AgentConfig likely needs to inherit:
- permission_checker derived from the delegated agent definition
- permission_policy when available
Depending on the intended product model, the child run may also need a deliberate confirmation-manager policy decision instead of silently defaulting to none.
Expected result after fix
Delegated agents invoked through task / parallel_task should execute tools according to their declared permission policy instead of unexpectedly hitting Ask and MissingConfirmationManager.
Temporary workaround
From an external host, there does not appear to be a complete workaround while still using builtin task / parallel_task for real delegated execution.
Changing worker names, kinds, prompts, or outer registration does not solve the core problem because the permission loss happens when the child AgentConfig is assembled inside the task tool path.
Bug Report: task / parallel_task child runs drop agent permission configuration and safe-deny tool execution
Summary
Delegated child runs launched through the builtin task / parallel_task path do not inherit the selected agent's permission checker into the child AgentConfig.
As a result, child tool calls fall back to Ask, and when no confirmation manager is present they are safe-denied with a MissingConfirmationManager error even when the delegated agent definition already carries an explicit allow policy.
This was observed from an external host integration, but the controlling code path appears to be inside A3S Code core rather than in host-side worker registration.
Impact
Environment
Expected behavior
When a delegated agent definition already has an explicit permission policy, the child run created by task / parallel_task should inherit that policy into its child AgentConfig in the same way the normal agent binding path does.
If the delegated agent definition allows write, edit, bash, or other tools, the child run should be able to execute those tools without unexpectedly falling back to Ask.
Actual behavior
The delegated child run is created with a fresh AgentConfig built from defaults plus prompt/tools/max_tool_rounds only.
That default AgentConfig has:
The safety gate then does this:
The resulting runtime error is the MissingConfirmationManager-style denial:
Tool '' requires confirmation but no HITL confirmation manager is configured.
Why this looks like a core bug instead of a host configuration bug
The host can already supply worker definitions with explicit permissions.
The apparent gap is that the task child-run path does not carry those permissions into child AgentConfig, even though the normal session binding path already has logic for that.
Relevant code paths:
Relevant source evidence
1. task child path manually builds a fresh AgentConfig
In Code/core/src/tools/task.rs, the child run is constructed with a manually assembled AgentConfig:
That means the child config does not receive the selected agent's permission_checker or confirmation_manager.
The same block only sets a deny-only guard policy on ToolExecutor:
That guard is not equivalent to populating child AgentConfig.permission_checker for the safety gate.
2. The normal binding path already knows how to apply permissions
In Code/core/src/agent_api/agent_binding.rs:
So there is already a canonical path that propagates agent-definition permissions correctly.
3. AgentConfig defaults to no permission checker and no confirmation manager
In Code/core/src/agent.rs default AgentConfig:
4. The safety gate explicitly turns that into Ask, then safe deny
In Code/core/src/safety_gate.rs:
5. Existing tests already document this behavior
In Code/core/src/agent/tests.rs:
So the current runtime behavior is internally consistent, but the task child-run path appears to be dropping the configuration needed to avoid Ask.
Minimal conceptual reproduction
Suggested fix
The child run created in Code/core/src/tools/task.rs should populate child AgentConfig using the same effective permission propagation model as the normal agent-binding path.
At minimum, the child AgentConfig likely needs to inherit:
Depending on the intended product model, the child run may also need a deliberate confirmation-manager policy decision instead of silently defaulting to none.
Expected result after fix
Delegated agents invoked through task / parallel_task should execute tools according to their declared permission policy instead of unexpectedly hitting Ask and MissingConfirmationManager.
Temporary workaround
From an external host, there does not appear to be a complete workaround while still using builtin task / parallel_task for real delegated execution.
Changing worker names, kinds, prompts, or outer registration does not solve the core problem because the permission loss happens when the child AgentConfig is assembled inside the task tool path.