Bug Description
Two problems in what AgentResult reports after waitForResult():
getEvents() is always an empty list. Events are only populated on the streaming path.
- Tool names come from the task type, so every tool kind except plain workers is mislabelled: an
HTTP tool is reported as "HTTP", an MCP tool as "CALL_MCP_TOOL", an agent used as a tool as
"SUB_WORKFLOW", a human tool as "HUMAN", and an image tool as "GENERATE_IMAGE".
Tool calls are also missed entirely for non-OpenAI providers, because selection keys on the
provider's tool-call ID format.
Root Cause
All in conductor-client-ai/src/main/java/org/conductoross/conductor/ai/model/AgentHandle.java
unless noted.
Events dropped. :367 (in buildResult) and :469 (in fromWorkflow) pass null for the
constructor's events parameter, and AgentResult.java:48 normalizes it to an empty list, so
nothing signals that nothing was collected. Both are reached from waitForResult() (:82).
AgentStream.java:321 populates it properly.
Name taken from the task type. :406, tc.put("name", taskType). That is correct only for a
worker tool, because Conductor sets an executed SIMPLE task's taskType to the task's own name
(SimpleTaskMapper.java:86 in conductor-oss/conductor). Every other tool kind carries its
system task type there.
The real name is available and thrown away. A tool task's inputData:
{"_agent_tool_name": "get_weather", "_agent_state": {},
"method": "get_weather", "city": "San Francisco"}
:412-418 strips method as an internal key, and neither _agent_tool_name nor
getTaskDefName() is read on this path.
The streaming path does not have this defect: it takes the name from the server
(AgentEvent.java:198, data.get("toolName")). So for the tool kinds the server emits events for,
the two paths report the same call under different names.
Selection keys on the provider's tool-call ID. :402-404:
if (refName != null && refName.startsWith("call_") && outputData != null) {
The server does not add a call_ prefix. It seeds the reference from the provider's
toolCall.id(), falling back to a UUID, then appends the fork index and loop iteration, giving
call_PMnNIdOPvm9EQ8e6tn2kbxPY_0__1 for OpenAI. Anthropic IDs start toolu_ and are not matched.
Adding toolu_ is not a fix, since the next provider picks its own format.
There is also no system-task filter beyond LLM_CHAT_COMPLETE (:392-398), so selection rests
entirely on the reference-name prefix.
Steps to Reproduce
AgentResult result = handle.waitForResult();
result.getEvents(); // [] always, whatever the agent did
For naming, register an agent with one HTTP tool and check
result.getToolCalls().get(0).get("name"), which is "HTTP". For detection, run any agent against
an Anthropic-backed model and getToolCalls() is empty.
Expected Behavior
Populate events on the non-streaming path, or make the empty case distinguishable from "no events
occurred".
Identify a tool task by task type, allowlisting off the server's ToolCompiler.TYPE_MAP plus the
worker case, and resolve the name from inputData._agent_tool_name, then inputData.method, then
getTaskDefName(). Never from the reference name, which carries provider-controlled data.
_agent_tool_name is the only key the server sets for every tool kind.
Both paths should report the same name for the same call.
Additional Notes
Verified against origin/main @ eda9c6a3f.
extractFromTasks (:382) has no unit test, and the e2e suite verifies that tools run via a
side-effect flag inside the tool body rather than by asserting on getToolCalls(), so the
extraction is not covered at either level.
A related server-side issue is filed against conductor-oss/conductor:
AgentEventListener.isToolTask excludes HTTP, CALL_MCP_TOOL, SUB_WORKFLOW and HUMAN, so
those four kinds emit no tool events on the streaming path either. Fixing this SDK gets their names
right in getToolCalls(). Getting them onto the stream needs that server fix as well, and for HTTP
and agent-as-tool it needs a third change, since those complete as async system tasks that never
notify the task listener.
Same family of defects filed against python-sdk, javascript-sdk and csharp-sdk.
Bug Description
Two problems in what
AgentResultreports afterwaitForResult():getEvents()is always an empty list. Events are only populated on the streaming path.HTTP tool is reported as
"HTTP", an MCP tool as"CALL_MCP_TOOL", an agent used as a tool as"SUB_WORKFLOW", a human tool as"HUMAN", and an image tool as"GENERATE_IMAGE".Tool calls are also missed entirely for non-OpenAI providers, because selection keys on the
provider's tool-call ID format.
Root Cause
All in
conductor-client-ai/src/main/java/org/conductoross/conductor/ai/model/AgentHandle.javaunless noted.
Events dropped.
:367(inbuildResult) and:469(infromWorkflow) passnullfor theconstructor's
eventsparameter, andAgentResult.java:48normalizes it to an empty list, sonothing signals that nothing was collected. Both are reached from
waitForResult()(:82).AgentStream.java:321populates it properly.Name taken from the task type.
:406,tc.put("name", taskType). That is correct only for aworker tool, because Conductor sets an executed SIMPLE task's
taskTypeto the task's own name(
SimpleTaskMapper.java:86inconductor-oss/conductor). Every other tool kind carries itssystem task type there.
The real name is available and thrown away. A tool task's
inputData::412-418stripsmethodas an internal key, and neither_agent_tool_namenorgetTaskDefName()is read on this path.The streaming path does not have this defect: it takes the name from the server
(
AgentEvent.java:198,data.get("toolName")). So for the tool kinds the server emits events for,the two paths report the same call under different names.
Selection keys on the provider's tool-call ID.
:402-404:The server does not add a
call_prefix. It seeds the reference from the provider'stoolCall.id(), falling back to a UUID, then appends the fork index and loop iteration, givingcall_PMnNIdOPvm9EQ8e6tn2kbxPY_0__1for OpenAI. Anthropic IDs starttoolu_and are not matched.Adding
toolu_is not a fix, since the next provider picks its own format.There is also no system-task filter beyond
LLM_CHAT_COMPLETE(:392-398), so selection restsentirely on the reference-name prefix.
Steps to Reproduce
For naming, register an agent with one HTTP tool and check
result.getToolCalls().get(0).get("name"), which is"HTTP". For detection, run any agent againstan Anthropic-backed model and
getToolCalls()is empty.Expected Behavior
Populate
eventson the non-streaming path, or make the empty case distinguishable from "no eventsoccurred".
Identify a tool task by task type, allowlisting off the server's
ToolCompiler.TYPE_MAPplus theworker case, and resolve the name from
inputData._agent_tool_name, theninputData.method, thengetTaskDefName(). Never from the reference name, which carries provider-controlled data._agent_tool_nameis the only key the server sets for every tool kind.Both paths should report the same name for the same call.
Additional Notes
Verified against
origin/main@eda9c6a3f.extractFromTasks(:382) has no unit test, and the e2e suite verifies that tools run via aside-effect flag inside the tool body rather than by asserting on
getToolCalls(), so theextraction is not covered at either level.
A related server-side issue is filed against
conductor-oss/conductor:AgentEventListener.isToolTaskexcludesHTTP,CALL_MCP_TOOL,SUB_WORKFLOWandHUMAN, sothose four kinds emit no tool events on the streaming path either. Fixing this SDK gets their names
right in
getToolCalls(). Getting them onto the stream needs that server fix as well, and for HTTPand agent-as-tool it needs a third change, since those complete as async system tasks that never
notify the task listener.
Same family of defects filed against
python-sdk,javascript-sdkandcsharp-sdk.