Skip to content

Bug Report: task / parallel_task child runs drop agent permission configuration and safe-deny tool execution #28

@liuzhixuan99

Description

@liuzhixuan99

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:

  1. No permission checker means permission_decision falls back to Ask.
  2. 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

  1. 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.
  2. Invoke that agent through task or parallel_task.
  3. Inside the child run, call a tool such as write.
  4. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions