Component
hyperforge.harness_sdk (AgentHarness._execute_tool_call, HarnessTool.execute)
Summary
When the Harness executes a tool call, the call's id is emitted in the TOOL_REQUESTED event and then the handler is invoked with only the harness and the validated input (HarnessTool.execute → await self.handler(harness, value)). The handler has no public way to learn which tool call it is executing:
AgentHarness._execute_tool_call emits TOOL_REQUESTED with call.id, then calls tool.execute(self, call.arguments).
harness.turn_id is a public property, but there is no public accessor for the active HarnessToolCall (the only call-related attributes on AgentHarness are the private _execute_tool_call/_execute_tool_calls methods).
Impact
Handlers that fan out nested work and emit their own lifecycle events cannot correlate those events with the parent tool call. Concrete example from an embedding application: a scoped "Code Mode" tool that runs restricted Python in a remote sandbox and exposes a fixed set of nested capabilities must emit TOOL_REQUESTED/TOOL_COMPLETED/TOOL_FAILED for each nested capability call; without the outer call id, those events cannot be parented to the harness's own tool-call event, and downstream consumers cannot reconstruct the hierarchy. The only workaround today is reading private harness state, which public-API consumers must not do.
Verified on hyperforge==1.0.0.post310.
Proposal (non-breaking)
Expose a read-only property, set and cleared around execution:
@property
def current_tool_call(self) -> HarnessToolCall | None:
return self._current_tool_call
# in _execute_tool_call:
self._current_tool_call = call
try:
...
finally:
self._current_tool_call = None
An alternative is passing a context object to handlers, but that changes the handler signature and belongs to a major-version design discussion; the property unblocks event correlation now without touching the handler contract.
Acceptance criteria
- During a tool execution,
harness.current_tool_call.id equals the call.id emitted in the corresponding TOOL_REQUESTED event.
- Outside of an execution (including after exceptions/cancellation),
current_tool_call is None.
Component
hyperforge.harness_sdk(AgentHarness._execute_tool_call,HarnessTool.execute)Summary
When the Harness executes a tool call, the call's id is emitted in the
TOOL_REQUESTEDevent and then the handler is invoked with only the harness and the validated input (HarnessTool.execute→await self.handler(harness, value)). The handler has no public way to learn which tool call it is executing:AgentHarness._execute_tool_callemitsTOOL_REQUESTEDwithcall.id, then callstool.execute(self, call.arguments).harness.turn_idis a public property, but there is no public accessor for the activeHarnessToolCall(the onlycall-related attributes onAgentHarnessare the private_execute_tool_call/_execute_tool_callsmethods).Impact
Handlers that fan out nested work and emit their own lifecycle events cannot correlate those events with the parent tool call. Concrete example from an embedding application: a scoped "Code Mode" tool that runs restricted Python in a remote sandbox and exposes a fixed set of nested capabilities must emit
TOOL_REQUESTED/TOOL_COMPLETED/TOOL_FAILEDfor each nested capability call; without the outer call id, those events cannot be parented to the harness's own tool-call event, and downstream consumers cannot reconstruct the hierarchy. The only workaround today is reading private harness state, which public-API consumers must not do.Verified on
hyperforge==1.0.0.post310.Proposal (non-breaking)
Expose a read-only property, set and cleared around execution:
An alternative is passing a context object to handlers, but that changes the handler signature and belongs to a major-version design discussion; the property unblocks event correlation now without touching the handler contract.
Acceptance criteria
harness.current_tool_call.idequals thecall.idemitted in the correspondingTOOL_REQUESTEDevent.current_tool_callisNone.