Before opening, please confirm:
Operating System
Ubuntu 24.04.3 LTS on WSL2 (kernel 6.6.87.2-microsoft-standard-WSL2)
Kiro Version
2.19.2
Bug Description
kiro-cli chat --resume-id <ID> silently fails to resume sessions created on the v2 or v3 agent engine. Instead of restoring the conversation, it starts a brand-new session with a new ID, and reports no error or warning. Sessions created on the default (classic) path resume correctly, so the defect is specific to v2/v3 session lookup.
Feature used: headless CLI (kiro-cli chat --no-interactive) with --output-format stream-json, which was added in 2.19.2 (requested in #9066).
Intended task: use kiro-cli as a conversation engine from an orchestration tool, running a multi-turn flow (plan → implement → review → fix) as a series of separate processes. Each step captures its session ID from the stream-json output and passes it to --resume-id on the next step so context carries forward.
This is currently impossible, because the two halves are mutually exclusive:
--output-format stream-json — the only machine-readable way to obtain a run's session ID — requires --agent-engine v2 or v3. It refuses to run on v1.
--resume-id only resolves sessions in the classic (v1) store.
So the only path that returns a usable session ID produces IDs that cannot be resumed, and the only path whose IDs can be resumed cannot tell you what its ID is.
Impact on workflow: the silence is the damaging part. A multi-turn pipeline exits 0 on every step and produces plausible-looking output, while in reality every turn starts from an empty context. There is nothing to detect — no error, no warning, no non-zero exit. The only way to notice is to inspect the emitted sessionId and observe that it differs from the one you passed in, or to catch the agent contradicting earlier turns.
Steps to Reproduce
Run each turn in a clean, empty directory. This matters: if the reproduction script is on disk in the working directory, the agent may read the passphrase out of the file and appear to "remember" it, masking the bug.
-
Create an empty working directory and define two prompts:
WORK=/tmp/clean-9066
mkdir -p "$WORK" && cd "$WORK"
P1="The passphrase is BLUE-SEVEN. Remember it. Reply OK only."
P2="What is the passphrase? Answer in one line. Do not use any tools."
-
Turn 1 — start a headless conversation on the v2 engine and capture its session ID from the stream-json output:
SID=$(kiro-cli chat --agent-engine v2 --output-format stream-json --trust-tools= "$P1" \
| jq -r 'select(.type=="runFinished").data.sessionId')
echo "$SID"
-
Turn 2 — resume that session and ask for the passphrase back:
kiro-cli chat --agent-engine v2 --resume-id "$SID" --output-format stream-json --trust-tools= "$P2" \
| jq -r 'select(.type=="runFinished").data | .sessionId, .finalText'
-
Observe that the sessionId printed in step 3 is different from $SID, and that finalText shows the agent has no knowledge of the passphrase. No error, warning, or non-zero exit accompanies this.
-
Repeat steps 2–4 with --agent-engine v3. Same failure (IDs are sess_-prefixed).
-
Control case — the default engine resumes correctly. Note this path cannot use stream-json, so the ID has to be scraped from --list-sessions:
kiro-cli chat --trust-tools= "$P1"
CSID=$(kiro-cli chat --list-sessions -f json | jq -r '.[0].sessions[0].sessionId')
kiro-cli chat --wrap never --resume-id "$CSID" --trust-tools= \
"Repeat the passphrase exactly. One line only."
This answers BLUE-SEVEN.
-
Confirm that stream-json cannot be used on the engine that does resume:
kiro-cli chat --agent-engine v1 --output-format stream-json "hi"
Expected Behavior
Two separate expectations, in priority order.
-
--resume-id should resolve session IDs regardless of which store holds them. Passing an ID obtained from runFinished.sessionId back into --resume-id should restore that conversation and continue it — the same behavior the classic path already has. In the reproduction above, step 3 should print the same sessionId it was given and finalText: BLUE-SEVEN.
If cross-store lookup is undesirable, then at minimum expose a selector for it. --delete-session already accepts --session-source <v1|v2>, but that flag is hard-wired to --delete-session and cannot be combined with --resume-id (see Additional Context), so a caller has no way to say which store to search.
-
An unresolvable --resume-id must fail loudly. Silently substituting a new session is the worst possible outcome for automation: the pipeline reports success while every turn runs with no context. Expected instead:
- a
runError event on the stream-json stream, e.g.
{"type":"runError","data":{"stage":"session","message":"session <ID> not found"}}
- a non-zero exit code
This is how the engine/format mismatch is already handled, and it works well:
{"type":"runError","data":{"sessionId":null,"stage":"engine","message":"--output-format stream-json is not supported on the v1 engine. Pass --agent-engine v2 (or v3)."}}
error: --output-format stream-json is not supported on the v1 engine. Pass --agent-engine v2 (or v3).
Session-not-found should behave the same way.
Note that even if (1) is deferred, fixing (2) alone would make this survivable — the failure would at least be detectable by the calling tool.
Conversation ID
Not applicable — this is a CLI issue, not raised from the IDE, so no conversation ID was auto-populated. The relevant identifiers are the session IDs from the reproduction run:
| Engine |
Turn 1 session ID (passed to --resume-id) |
Turn 2 session ID (actually used) |
| v2 |
8255c6fc-4bd8-460d-9e7c-794500e0805f |
32a6525a-2c18-467d-8319-e3f13620d95d |
| v3 |
sess_12cdc4b5-166e-4222-8b4c-0a08b8ca4e64 |
sess_8a87a715-6bd6-48d8-b232-d66ddcc06539 |
| classic (control, works) |
7b7d00f2-2195-498c-a590-0ad27fc0c674 |
same ID — resumed correctly |
Additional Context
Actual output from the reproduction
### kiro-cli 2.19.2 (Ubuntu 24.04.3 LTS on WSL2)
===== engine = v2 =====
turn 1:
sessionId : 8255c6fc-4bd8-460d-9e7c-794500e0805f
finalText : OK
turn 2 (--resume-id 8255c6fc-4bd8-460d-9e7c-794500e0805f):
sessionId : 32a6525a-2c18-467d-8319-e3f13620d95d
finalText : I don't have a passphrase in my context — nothing in this conversation or my instructions contains one.
===== engine = v3 =====
turn 1:
sessionId : sess_12cdc4b5-166e-4222-8b4c-0a08b8ca4e64
finalText : OK
turn 2 (--resume-id sess_12cdc4b5-166e-4222-8b4c-0a08b8ca4e64):
sessionId : sess_8a87a715-6bd6-48d8-b232-d66ddcc06539
finalText : I'm not sure — there's no context indicating what "passphrase" refers to. Which passphrase are you asking about?
===== control: default engine, no stream-json =====
sessionId (via --list-sessions): 7b7d00f2-2195-498c-a590-0ad27fc0c674
turn 2 (--resume-id 7b7d00f2-...):
> BLUE-SEVEN
===== v1 engine + stream-json =====
{"type":"runError","data":{"sessionId":null,"stage":"engine","message":"--output-format stream-json is not supported on the v1 engine. Pass --agent-engine v2 (or v3)."}}
error: --output-format stream-json is not supported on the v1 engine. Pass --agent-engine v2 (or v3).
The session data is written correctly — only the lookup fails
--list-sessions -f json after the v2 run shows two independent sessions rather than one extended session, and turn 1's session is fully persisted:
{"sessionId": "32a6525a-2c18-467d-8319-e3f13620d95d", "source": "v2", "messageCount": 2, "title": "What is the passphrase? Answer in one line. Do not use any tools."}
{"sessionId": "8255c6fc-4bd8-460d-9e7c-794500e0805f", "source": "v2", "messageCount": 2, "title": "The passphrase is BLUE-SEVEN. Remember it. Reply OK only."}
By contrast, the classic control session was extended in place — messageCount went 2 → 4 → 6 over three turns on the same ID, with no duplicate session created:
{"sessionId": "7b7d00f2-2195-498c-a590-0ad27fc0c674", "source": "classic", "messageCount": 6, "title": "The passphrase is BLUE-SEVEN. Remember it. Reply OK only."}
Summary of the catch-22
| Path |
source in --list-sessions |
Can emit its session ID? |
--resume-id works? |
default engine, no stream-json |
classic |
No |
Yes |
--agent-engine v2 + stream-json |
v2 |
Yes |
No |
--agent-engine v3 + stream-json |
v3 |
Yes |
No |
Suspected cause
A session-store resolution gap rather than a resume bug — --resume-id appears to search only the classic/v1 store while the v2/v3 engines write to their own stores. Supporting evidence:
Also worth noting that --session-source only offers v1 and v2 — there is no v3 value — while --list-sessions reports source: "v3" for sessions created with --agent-engine v3. The store enumeration appears to have fallen behind the engine list.
Workarounds attempted
1. Point --resume-id at the right store with --session-source. Not possible — the flag is hard-wired to --delete-session:
$ kiro-cli chat --agent-engine v2 --session-source v2 \
--resume-id 8255c6fc-4bd8-460d-9e7c-794500e0805f \
--output-format stream-json --trust-tools= "test"
error: the following required arguments were not provided:
--delete-session <SESSION_ID>
Usage: kiro-cli-chat chat --delete-session <SESSION_ID> --agent-engine <ENGINE> --session-source <v1|v2> --resume-id <SESSION_ID> --output-format <OUTPUT_FORMAT> --trust-tools <TOOL_NAMES> <INPUT>
2. Replay the full conversation history in the prompt on every invocation, keeping all state on the caller's side. This works, but costs tokens linearly in turn count and forfeits the benefit that #9066 was asking for. It is what I am doing now.
Related
Environment notes
kiro-cli 2.19.2, confirmed latest via kiro-cli update ("2.19.2 is the latest version").
kiro-cli chat --help documents --agent-engine as defaulting to v2, but on this install --output-format stream-json fails with the v1-engine error unless --agent-engine v2 is passed explicitly, so the effective default appears to be v1. Minor, but it makes the feature look broken on first use.
Before opening, please confirm:
Operating System
Ubuntu 24.04.3 LTS on WSL2 (kernel 6.6.87.2-microsoft-standard-WSL2)
Kiro Version
2.19.2
Bug Description
kiro-cli chat --resume-id <ID>silently fails to resume sessions created on the v2 or v3 agent engine. Instead of restoring the conversation, it starts a brand-new session with a new ID, and reports no error or warning. Sessions created on the default (classic) path resume correctly, so the defect is specific to v2/v3 session lookup.Feature used: headless CLI (
kiro-cli chat --no-interactive) with--output-format stream-json, which was added in 2.19.2 (requested in #9066).Intended task: use kiro-cli as a conversation engine from an orchestration tool, running a multi-turn flow (plan → implement → review → fix) as a series of separate processes. Each step captures its session ID from the
stream-jsonoutput and passes it to--resume-idon the next step so context carries forward.This is currently impossible, because the two halves are mutually exclusive:
--output-format stream-json— the only machine-readable way to obtain a run's session ID — requires--agent-engine v2orv3. It refuses to run on v1.--resume-idonly resolves sessions in theclassic(v1) store.So the only path that returns a usable session ID produces IDs that cannot be resumed, and the only path whose IDs can be resumed cannot tell you what its ID is.
Impact on workflow: the silence is the damaging part. A multi-turn pipeline exits 0 on every step and produces plausible-looking output, while in reality every turn starts from an empty context. There is nothing to detect — no error, no warning, no non-zero exit. The only way to notice is to inspect the emitted
sessionIdand observe that it differs from the one you passed in, or to catch the agent contradicting earlier turns.Steps to Reproduce
Run each turn in a clean, empty directory. This matters: if the reproduction script is on disk in the working directory, the agent may read the passphrase out of the file and appear to "remember" it, masking the bug.
Create an empty working directory and define two prompts:
Turn 1 — start a headless conversation on the v2 engine and capture its session ID from the
stream-jsonoutput:Turn 2 — resume that session and ask for the passphrase back:
Observe that the
sessionIdprinted in step 3 is different from$SID, and thatfinalTextshows the agent has no knowledge of the passphrase. No error, warning, or non-zero exit accompanies this.Repeat steps 2–4 with
--agent-engine v3. Same failure (IDs aresess_-prefixed).Control case — the default engine resumes correctly. Note this path cannot use
stream-json, so the ID has to be scraped from--list-sessions:This answers
BLUE-SEVEN.Confirm that
stream-jsoncannot be used on the engine that does resume:kiro-cli chat --agent-engine v1 --output-format stream-json "hi"Expected Behavior
Two separate expectations, in priority order.
--resume-idshould resolve session IDs regardless of which store holds them. Passing an ID obtained fromrunFinished.sessionIdback into--resume-idshould restore that conversation and continue it — the same behavior theclassicpath already has. In the reproduction above, step 3 should print the samesessionIdit was given andfinalText: BLUE-SEVEN.If cross-store lookup is undesirable, then at minimum expose a selector for it.
--delete-sessionalready accepts--session-source <v1|v2>, but that flag is hard-wired to--delete-sessionand cannot be combined with--resume-id(see Additional Context), so a caller has no way to say which store to search.An unresolvable
--resume-idmust fail loudly. Silently substituting a new session is the worst possible outcome for automation: the pipeline reports success while every turn runs with no context. Expected instead:runErrorevent on thestream-jsonstream, e.g.{"type":"runError","data":{"stage":"session","message":"session <ID> not found"}}This is how the engine/format mismatch is already handled, and it works well:
Session-not-found should behave the same way.
Note that even if (1) is deferred, fixing (2) alone would make this survivable — the failure would at least be detectable by the calling tool.
Conversation ID
Not applicable — this is a CLI issue, not raised from the IDE, so no conversation ID was auto-populated. The relevant identifiers are the session IDs from the reproduction run:
8255c6fc-4bd8-460d-9e7c-794500e0805f32a6525a-2c18-467d-8319-e3f13620d95dsess_12cdc4b5-166e-4222-8b4c-0a08b8ca4e64sess_8a87a715-6bd6-48d8-b232-d66ddcc065397b7d00f2-2195-498c-a590-0ad27fc0c674Additional Context
Actual output from the reproduction
The session data is written correctly — only the lookup fails
--list-sessions -f jsonafter the v2 run shows two independent sessions rather than one extended session, and turn 1's session is fully persisted:{"sessionId": "32a6525a-2c18-467d-8319-e3f13620d95d", "source": "v2", "messageCount": 2, "title": "What is the passphrase? Answer in one line. Do not use any tools."} {"sessionId": "8255c6fc-4bd8-460d-9e7c-794500e0805f", "source": "v2", "messageCount": 2, "title": "The passphrase is BLUE-SEVEN. Remember it. Reply OK only."}By contrast, the
classiccontrol session was extended in place —messageCountwent2 → 4 → 6over three turns on the same ID, with no duplicate session created:{"sessionId": "7b7d00f2-2195-498c-a590-0ad27fc0c674", "source": "classic", "messageCount": 6, "title": "The passphrase is BLUE-SEVEN. Remember it. Reply OK only."}Summary of the catch-22
sourcein--list-sessions--resume-idworks?stream-jsonclassic--agent-engine v2+stream-jsonv2--agent-engine v3+stream-jsonv3Suspected cause
A session-store resolution gap rather than a resume bug —
--resume-idappears to search only theclassic/v1 store while the v2/v3 engines write to their own stores. Supporting evidence:--delete-sessionhas an explicit--session-source <v1|v2>selector;--resume-idhas no equivalent and cannot borrow it (see below).--delete-sessionreturning "session not found" for v3 sessions.Also worth noting that
--session-sourceonly offersv1andv2— there is nov3value — while--list-sessionsreportssource: "v3"for sessions created with--agent-engine v3. The store enumeration appears to have fallen behind the engine list.Workarounds attempted
1. Point
--resume-idat the right store with--session-source. Not possible — the flag is hard-wired to--delete-session:2. Replay the full conversation history in the prompt on every invocation, keeping all state on the caller's side. This works, but costs tokens linearly in turn count and forfeits the benefit that #9066 was asking for. It is what I am doing now.
Related
--output-format stream-jsonshipped in 2.19.2 and solves session-ID retrieval; this issue is about the resume half being unreachable as a result.--delete-sessionreports "session not found" for v3 sessions. Likely the same root cause.Environment notes
kiro-cli 2.19.2, confirmed latest viakiro-cli update("2.19.2 is the latest version").kiro-cli chat --helpdocuments--agent-engineas defaulting to v2, but on this install--output-format stream-jsonfails with the v1-engine error unless--agent-engine v2is passed explicitly, so the effective default appears to be v1. Minor, but it makes the feature look broken on first use.