Name every tool kind correctly and populate events when polling - #172
Merged
Conversation
waitForResult() reported an HTTP tool as "HTTP", an MCP tool as "CALL_MCP_TOOL", an agent-as-tool as "SUB_WORKFLOW", a human tool as "HUMAN" and an image tool as "GENERATE_IMAGE" — the tool name came from getTaskType(), which is only the tool's own name for a worker, because Conductor rewrites an executed SIMPLE task's type to the task name. It also missed tool calls entirely on non-OpenAI providers: selection keyed on the reference name starting "call_", which is the provider's tool-call id format, so an Anthropic-backed run (toolu_) recorded none. And getEvents() was hard-coded to null on this path, so a run that called three tools looked like one that did nothing. - identify a tool task by task type, allowlisting off the server's ToolCompiler.TYPE_MAP plus _agent_tool_name, never the reference name - resolve the name from inputData._agent_tool_name, then inputData.method, then getTaskDefName() - synthesize tool_call/tool_result events per tool task and close with a terminal done/error event, so both paths report the same call the same way - skip a tool task that has neither finished nor produced output, and report the whole output map for a tool whose output isn't wrapped in "result" - strip every _-prefixed key from a streamed event's args, as the polled path already did extractFromTasks had no coverage at either level; AgentHandleToolExtractionTest covers it through the fromWorkflow seam.
Detection rested entirely on the server tagging a tool task's input with _agent_tool_name. Against a server predating that tag, every tool kind whose per-kind compile step replaces the task input carries nothing that names it, so isToolTask matched none of them and the calls vanished from getToolCalls() rather than arriving under a wrong name. Two tool calls became zero. TOOL_TASK_TYPES could not cover for it: an executed worker tool reports its own name as its taskType, so "SIMPLE" in that set never matches a task that ran, and the type-and-method branch only ever reached the system-task kinds. - fall back to the dynamic fork when no task carries the tag: an agent dispatches tool calls through FORK_JOIN_DYNAMIC, and Conductor records the reference names it forked on the fork task's own input - recognise an executed worker tool by its type agreeing with its task-def name - keep the tag authoritative where the server sets it, because an agent can fan out dynamically for reasons of its own, so the fork list is a fallback rather than a second source of truth Behaviour against a tagging server is unchanged.
Contributor
Author
|
This PR fixes the tool names in The server picks which tasks become stream events in Tracked in conductor-oss/conductor#1584. This PR doesn't move it. |
The untagged-server fallback compared a task's reference name to the fork list verbatim, and the two never agree for a real agent. Conductor records forkedTasks when it maps the FORK_JOIN_DYNAMIC, before the enclosing DO_WHILE appends __<iteration> to each task it schedules, so the list holds toolu_ab_0 while the tool task is toolu_ab_0__1. Every tool call inside the ReAct loop failed the lookup, which is all of them. Verified against a live server: a dynamic fork inside a DO_WHILE records forkedTasks ["toolu_99_0"] and schedules toolu_99_0__1. The three earlier tests agreed with the defect because their fork lists carried the iteration suffix, which the server never does. - normalize both sides on the __<iteration> suffix, matched only at the end of the name rather than TaskUtils' split on the first "__" - fix the fixtures to record fork lists as the server does, and cover a call forked inside the loop - share one internal-key predicate with AgentEvent so both paths strip the same set structurally, rather than by a test asserting they agree - name the tool-call and tool-result event builders - warn rather than debug when the task walk fails, since the empty result it leaves is indistinguishable from a run that used no tools
ambiorix2099
marked this pull request as ready for review
September 9, 2026 17:03
NicholasDCole
approved these changes
Sep 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request type
Summary
waitForResult()named every non-worker tool after its task type, returned no events, and found no tool calls at all against Anthropic.AgentHandle.extractFromTaskstook the name fromgetTaskType(), correct only for a worker; requiredrefName.startsWith("call_"), OpenAI's tool-call id format; and passednullforevents._agent_tool_name, name from it thenmethodthengetTaskDefName(), and synthesize the missing events.User impact
Callers could not tell which tool ran, or a run that used three tools from one that used none.
getToolCalls()getEvents()[get_weather, HTTP][][get_weather, fetch_page]tool_call, tool_result, tool_call, tool_result, doneRows captured by running both extractions over workflow records a live server executed, tool tasks dispatched by hand. Against Anthropic,
beforeis[]. Polled events carry nothinkingormessage.On a server that sets no
_agent_tool_name, detection falls back to the dynamic fork and the name tomethodor the task's own name; an agent-as-tool and a media tool still report their task-def name there, which is all the record keeps of them.Changes
AgentHandle.java: detect by_agent_tool_namewith the dynamic fork as fallback, resolve the name, synthesize eventsAgentEvent.java: strip every_-prefixed argument key (the only streamed change)AgentResult.java,docs/agents/reference/runtime.md: state whatgetEvents()holds per pathAgentHandleToolExtractionTest.java: new, 15 tests over thefromWorkflowseamFixes #170