MCPcopy Create free account
hub / github.com/agentforce314/clawcodex / create_subagent_context

Function create_subagent_context

src/agent/subagent_context.py:54–187  ·  view source on GitHub ↗

Create an isolated ToolContext for subagents. Mirrors createSubagentContext() from typescript/src/utils/forkedAgent.ts. By default, ALL mutable state is isolated to prevent interference: - read_file_fingerprints: cloned from parent - abort_controller: new controller linked to paren

(
    parent_context: ToolContext,
    overrides: SubagentContextOverrides | None = None,
)

Source from the content-addressed store, hash-verified

52
53
54def create_subagent_context(
55 parent_context: ToolContext,
56 overrides: SubagentContextOverrides | None = None,
57) -> ToolContext:
58 """Create an isolated ToolContext for subagents.
59
60 Mirrors createSubagentContext() from typescript/src/utils/forkedAgent.ts.
61
62 By default, ALL mutable state is isolated to prevent interference:
63 - read_file_fingerprints: cloned from parent
64 - abort_controller: new controller linked to parent (parent abort propagates)
65 - permission_context: wrapped to set should_avoid_permission_prompts
66 - Mutation callbacks: no-op
67 - Fresh collections: todos, tasks, outbox
68
69 Callers can:
70 - Override specific fields via the overrides parameter
71 - Explicitly opt-in to sharing specific callbacks
72 """
73 if overrides is None:
74 overrides = SubagentContextOverrides()
75
76 # --- Abort controller ---
77 # Priority: explicit override > share parent's > new child linked to parent.
78 # ``parent_context.abort_controller`` is now non-optional on the
79 # ``ToolContext`` dataclass, so the legacy "parent has no controller"
80 # branch is gone — every parent context carries a real controller.
81 if overrides.abort_controller is not None:
82 abort_controller = overrides.abort_controller
83 elif overrides.share_abort_controller:
84 abort_controller = parent_context.abort_controller
85 else:
86 abort_controller = create_child_abort_controller(parent_context.abort_controller)
87
88 # --- Permission context ---
89 # If sharing abort controller, it's interactive and can show UI.
90 # Otherwise, set should_avoid_permission_prompts.
91 if overrides.permission_context is not None:
92 permission_context = overrides.permission_context
93 elif overrides.share_abort_controller:
94 # Interactive agent — share parent's permission context
95 permission_context = parent_context.permission_context
96 else:
97 # Background agent — suppress permission prompts
98 permission_context = _wrap_avoid_prompts(parent_context.permission_context)
99
100 # --- Read file state (fingerprints) ---
101 # TS behaviour: subagents start with an EMPTY fingerprint cache.
102 # They have NOT read any files yet, so inheriting the parent's cache
103 # causes the Read tool to return "file_unchanged" for files the
104 # subagent has never seen, forcing wasteful Bash fallbacks.
105 if overrides.read_file_state is not None:
106 read_file_fingerprints = dict(overrides.read_file_state)
107 else:
108 read_file_fingerprints: dict[Any, Any] = {}
109
110 # --- Options ---
111 options = overrides.options if overrides.options is not None else parent_context.options

Calls 5

_wrap_avoid_promptsFunction · 0.85
QueryChainTrackingClass · 0.85
ToolContextClass · 0.85