fancy-soccer-23711
10/09/2026, 9:06 AMqwen3-coder-30b-fp8 model served by vLLM on a separate NVIDIA DGX Spark, connected through an OpenAI-compatible endpoint.
• vLLM configured with --tool-call-parser qwen3_coder and --enable-auto-tool-choice.
A simple parent–child smoke test worked once: the parent launched a child conversation, I watched the child run in Canvas, and its response returned to the parent. However, that success has not been repeatable despite many attempts. The problem I’m investigating is the child’s response not returning to the parent.
Has anyone encountered this with Canvas child conversations? Which logs or events should I check to determine whether the child’s final response was delivered to the parent, versus the parent model failing to process it? Could the tool-call parser configuration affect this handoff?
I’m asking specifically about Canvas child conversations, not SDK sub-agent delegation.limited-student-10747
10/09/2026, 6:03 PMlimited-student-10747
10/09/2026, 6:04 PMfancy-soccer-23711
10/09/2026, 9:58 PMlimited-student-10747
10/11/2026, 12:24 AMfresh-machine-37269
10/11/2026, 12:24 AMfresh-machine-37269
10/11/2026, 12:26 AMTaskExecutor.__call__ calls TaskManager.start_task(...), which runs the child LocalConversation to completion (_run_task → send_message → run() → _run_until_finished) and blocks until it reaches FINISHED.
The child's final response is then extracted with get_agent_final_response(events) — the last FinishAction.message or the last agent MessageEvent — and handed straight back to the parent inside the TaskObservation (or as an error/partial result if it stopped for a run limit, stuck, etc.). The parent doesn't query anything; it receives the result as the return value of its own tool call in the same turn. The child conversation itself is persisted (under the parent's subagents/ dir, or a temp dir), and resume=task_id re-runs it blocking again. So for TaskTool (and the sibling Delegate tool `spawn`/`delegate`, same blocking pattern) the answer is: always, by construction.
2. Canvas child conversations (launch_child_conversation) — only a launch receipt comes back, not the result
This path is deliberately fire-and-forget. The tool description in the Canvas repo is explicit: "The child runs on its own. It does not block you, you do not see its output, and it cannot see this conversation's history."
What is posted back to the parent automatically is a launch acknowledgement, and it happens at launch time — not completion. launch_child_conversation is a client-side tool, so the agent-server acks the call immediately; the frontend then does the real work and posts a machine message [child-conversation] {"status":"launched","conversation_id":…,"url":…,"initial_status":…} into the parent (reportLaunchResult → sendMessage). That's the child's id/URL/initial status, not its final answer.
When the child later finishes, nothing forwards its result into the parent. The parent/child relationship is persisted server-side (parent_conversation_id → the parent's sub_conversation_ids, added in software-agent-sdk #4188 / agent-server ≥ 1.37.1), but that link is used for discovery, recovery and deletion bookkeeping — not message delivery. There's no completion hook that injects the child's final message into the parent. To get the child's output the parent has to explicitly check back in on that conversation id (or a human relays it).
So Graham is right, and the docs' "its result is returned to the parent conversation" is misleading — it's really just the link/record that's returned. The one time it appeared to work was almost certainly the model (or you) going back and reading the child's conversation after the receipt, not a deterministic handoff. The tool-parser config can affect whether the model chooses to poll the child, but it can't create a delivery that the code never performs.
Practical takeaway: if you need a child's result delivered to the parent, use the SDK Task tool (blocking, result in the observation). If you're using Canvas child conversations, treat them as independent and have the parent explicitly read the child's conversation when you need its output.
This reply was drafted by an AI agent (OpenHands) on behalf of the user.limited-student-10747
10/11/2026, 12:30 AMfresh-machine-37269
10/11/2026, 12:31 AMOpenHands/docs → openhands/usage/agent-canvas/conversations.mdx, Child Conversations section:
"The child remains linked to its parent, and its result is returned to the parent conversation."That sentence conflates two different things. What's automatically returned is the launch receipt — the
[child-conversation] {"status":"launched","conversation_id":…,"url":…} message the frontend posts back at launch time. The child's final answer is not auto-delivered; the child runs independently and you have to open it to read its output. "Its result is returned to the parent conversation" reads naturally as the latter, which is exactly the misreading the user in the thread hit. It's made worse by the SDK Task tool genuinely being blocking and returning the sub-agent's result in the observation — same word "result", different behavior, no distinction drawn.
Issue opened: OpenHands/docs#925 — github.com/OpenHands/docs/issues/925
It quotes the current text, explains the launch-receipt-vs-final-result conflation, and has concrete acceptance criteria: drop the "result is returned" claim or qualify it as the launch receipt only; distinguish the automatic launch acknowledgement from the non-delivered final result; state the child is non-blocking/independent; and (if a Task-tool contrast is added) note that Task-tool delegation is blocking and does return the final response. It also cites the implementing code in both OpenHands/OpenHands and software-agent-sdk for the maintainers to verify against.
This reply was drafted by an AI agent (OpenHands) on behalf of the user.limited-student-10747
10/11/2026, 12:32 AMfancy-soccer-23711
10/11/2026, 2:16 AMlimited-student-10747
10/11/2026, 2:18 AM