Skip to content

Subagent child sessions export empty (0 messages, outcome null) despite successful completion #59136

Open

Description

@megadoom99

Summary

Subagent sessions created by command dispatch (or the subagent tool) return an empty export even after they run to completion:

GET /api/experimental/session/{childID}/export
→ { "data": { "info": { "outcome": null, "tokens": null, ... }, "messages": [] } }

The child demonstrably completed — the parent session contains the injected synthetic result:

<subagent sessionID="ses_..." state="completed" description="...">(full result text…)</subagent>

…so the run, tokens and transcript exist, but the child session's own export shows zero messages and outcome: null forever. GET /api/session?parentID=... lists the child, and its list entry carries real token/cost/outcome values — only the export projection is empty.

Impact

Any client that reads subagent transcripts (SDK consumers, analytics, test harnesses, resumability tooling) sees the child sessions as dead/never-run, even though they succeeded. In our testing this made successful subagent runs look like failures, because the only observable store (the child export) is empty while the actual result lives in the parent's synthetic message.

Reproduction

  1. Create a command bound to a subagent agent (agent: frontmatter pointing at a mode: subagent agent).
  2. Execute it via POST /api/session/{id}/command.
  3. Wait for the parent session to receive the synthetic <subagent sessionID=... state="completed"> message.
  4. Export the child session by that sessionID → 0 messages, outcome: null.

Observed consistently on OpenCode 2.1.4 (desktop app service, macOS 15 arm64), across both a glm-5.3 and a deepseek-v4.1 backend via an OpenAI-compatible provider.

Expected

The child session's export should contain its messages (the task prompt and the assistant's turns) and its final outcome, matching what the parent synthetic and the session list entry already know.

Activity

  1. opencode-agent commented on Oct 26, 2026

    @opencode-agent
    Contributor

    Thanks for the report and the reproduction steps.

    In v2.1.4, the export endpoint gets the session info from the same record that GET /api/session?parentID=... lists, and its response always includes a tokens object. If the session has no outcome, the outcome field is left out rather than set to null. So a response with "tokens": null and "outcome": null doesn't look like the endpoint's raw output. Your tooling may have reshaped it, or the request may have gone to a different server than the one that ran the subagent. To narrow it down, could you share:

    1. The raw, unedited response of curl -s <base-url>/api/experimental/session/<childID>/export for one affected child, run against the same server (with prompts redacted if needed).
    2. The base URL/port you sent it to, and how that server was started (the desktop app's service, or opencode serve from the CLI). You mention both 2.1.4 and CLI 2.1.2 in Subagent-bound command: prompt to freshly-created child session can be silently dropped (no error, no log) #59135.
    3. The raw entry for the same child from GET /api/session?parentID=<parentID>, and the parent's <subagent sessionID=...> line, so we can confirm the IDs match.

    You can reply here with the details or edit the issue. If you edit it, please also leave a short comment saying you've updated it, so we know when you're done editing.

    These issues are related, ordered by likelihood, though none looks like the same problem:

  2. megadoom99 commented on Oct 26, 2026

    @megadoom99
    Author

    Follow-up from testing: a related manifestation — when the subagent's final turn produces no text (e.g. it exhausts its step budget mid-tool-call before composing its summary), the job reports outcome: "succeeded" but the parent synthetic says Subagent completed without a text response. The child generated ~66k output tokens of work across its turns, all of which is unreachable: the child export is empty (this issue's main subject) and the synthetic only carries the last text message. Two consequences worth considering upstream: (1) the subagent completion payload could carry the accumulated final text or a transcript reference rather than only the last message; (2) a step-limit exhaustion arguably should not be a silent success.

  3. opencodejr commented on Oct 28, 2026

    @opencodejr

    Thanks for the report. I checked it against the v2.1.4 code. The export endpoint gets the session info with the same lookup as GET /api/session and reads messages from the same store. It leaves out only messages that haven't finished yet. Also, tokens is always present in session info and outcome is left out rather than set to null. So a response with "tokens": null, "outcome": null shouldn't be possible, and neither should a list entry that has real tokens while the export of the same session has none. That makes me think the JSON in the issue was paraphrased, or the export went to a different session or server.

    To work out what's happening, could you share, briefly and in your own words:

    • The raw, unedited responses, all for the same child session ID and from the same running service:
      • GET /api/session/{childID}
      • the matching entry from GET /api/session?parentID={parentID}
      • GET /api/session/{childID}/message
      • GET /api/experimental/session/{childID}/export
    • Whether the sessionID in the parent's <subagent …> message is exactly the child ID you exported.
    • Your command and agent frontmatter (leave out anything private).
    • Whether you get the same result with opencode serve instead of the desktop app's bundled service.

    You can reply here or edit the issue. If you edit it, please also leave a short comment saying you've updated it, so we know when you're done.

    Related issues, ordered by likelihood (none looks like an exact match):

  4. opencodejr commented on Oct 31, 2026

    @opencodejr

    I'm closing this as not planned because we haven't heard back. In v2.1.4 the export endpoint reads session info and messages from the same place as the session list. So the quoted output ("tokens": null, and real tokens in the list but not in the export) can't come from it. We needed the raw responses for one child session ID to see what's actually going on.

    If this still happens, please reply here with the unedited output of GET /api/session/{childID}, GET /api/session/{childID}/message and GET /api/experimental/session/{childID}/export, all from the same running service, and we'll reopen it. #59135 covers the related problem of a child session left with 0 messages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions