Node input is appended to the session as a role:"user" event, fabricating user turns
- Dominant language
- TypeScript
- Stars
- 1.4k
- Forks
- 205
- Avg merge
- 3d 16h
- Merged PRs (30d)
- 92
Description
`appendNodeInputAsUserTurn` writes an LlmAgent node's input into the session with `author: 'user'` and `toUserContent(...)` (`core/src/workflow/run_llm_agent_as_node.ts:80-102`). The Runner has already appended the real user message for the turn, so session history gains turns nobody typed — either the user's own text stored twice, or a JSON blob attributed to the user.
```bash
cd dev
cp ../samples/workflows/dynamic/sequence_route/agent.ts /tmp/sr/agent.ts
{ printf 'Hello\n'; sleep 15; printf 'exit\n'; } | npx adk run /tmp/sr/agent.ts --save_session --session_id sr1
npx adk run /tmp/sr/agent.ts --resume /tmp/sr/sr1.session.json
# [user]: Hello
# [city_generator_agent]: Paris
# [city_time_function]: {"timeInfo":"10:10 AM","city":"Paris"}
# [user]: {"timeInfo":"10:10 AM","city":"Paris"} <-- never typed
```
The duplicate is in the persisted `*.session.json` and in `GET /apps/.../sessions/...`, so it is not a render artifact. `dynamic/data_handling` shows the other shape: the user's own message stored twice, because the workflow forwards the user text unchanged. A bare `LlmAgent` with no Workflow stores exactly one user event per turn. Inflates memory ingestion, context compaction and token accounting.
Contributor guide
Assessment
This issue has not been assessed yet.