Keep a seat itself on every turn, not just its first - #74
Conversation
A hosted seat's session is cleared and reseeded from the host's log each turn. Seeding brings the runtime session up before the turn runs, and a session that already has one is not cold -- and only a cold turn composes its system prompt. So a seat had its persona on its first turn of an episode and none on any turn after: no role, no team, no company, just the episode brief. It still answered, which is why nothing complained. It simply was not being itself, from turn two onward, in every multi-turn episode. `EpisodeHost::persona` gives a host somewhere to hand the standing prompt back from, and the seeded history carries it at the head, where the turn reads it as the system message it would otherwise have composed. Only when there is history to seed: with none, seeding is skipped and the turn is cold, which is the one case that already renders the prompt itself. Defaulted to `None`, so a host with no standing prompt is unchanged. Co-Authored-By: Claude <noreply@anthropic.com>
Tiny Sweeper reviewTiny Sweeper reviewed this change across 6 lane(s) and found 1 active actionable finding(s). Detailed lane evidence and any incomplete work are listed below. State: Ready for maintainer review Review snapshot
Completeness: Complete What changedThe review could not produce a supported behavioral summary; inspect the cited changed surface and lane details below. FeaturesNone identified with supported citations. TestsNo supported feature-to-test mapping was produced. Test execution is not inferred. Findings
Before mergeNone. How this fits togetherflowchart LR
n0["BoundAgent"]:::impacted
n1["turn"]:::impacted
n2["new"]:::impacted
n3["HostedSeat"]:::impacted
n4["HostedRunner"]:::impacted
n5["seat"]:::impacted
n1 -->|calls| n2
n3 -->|implements| n0
n4 -->|uses| n3
n5 -->|calls| n2
n5 -->|uses| n3
classDef changed fill:#0d4429,stroke:#238636,color:#e6edf3
classDef impacted fill:#161b22,stroke:#6e7681,color:#c9d1d9
classDef flagged fill:#5a1e02,stroke:#d93f0b,color:#ffffff
classDef blocking fill:#67060c,stroke:#f85149,color:#ffffff
Agent review detailscritique
security
tests
commits
description
e2e
Evidence and run details
|
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (1)
Comment |
There was a problem hiding this comment.
tinysweeper found nothing blocking. Approving.
$0.0044 · 112,333 in / 10,041 out · 4,595 cached (4%) · ladder/vectors, gpt-5.6-luna, deepseek-v4-flash · 166 embedded
critique: $0.0015 · 46,741 in / 1,847 out · 2,035 cached (4%) · gpt-5.6-luna
security: $0.0022 · 46,478 in / 1,079 out · 0 cached (0%) · gpt-5.6-luna
tests: $0.0003 · 12,760 in / 1,341 out · 1,536 cached (12%) · deepseek-v4-flash
description: $0.0002 · 4,180 in / 3,480 out · 1,024 cached (24%) · deepseek-v4-flash
`main` has been red since #74. The Rust lane's clippy step and the Docs lane both fail on `missing documentation for a method` at `EpisodeHost::tool_prefix`, and every branch cut from main inherits it. Nothing was ever missing. `tool_prefix`'s doc block is intact -- it sits above `persona`, fused to `persona`'s own first line with no blank between them, and `tool_prefix` itself was left bare a few lines below. A merge slip, not a gap: the prose describing the prefix still reads correctly, just over the wrong method. Moving the method back under its own doc fixes both lanes. `cargo clippy --all-targets --all-features -- -D warnings` and `cargo doc --no-deps --all-features` are exit 0, and the suite is unchanged at 36 targets.
Summary
A hosted seat's session is cleared and reseeded from the host's log every turn. Seeding brings the runtime session up before the turn runs, and a session that already has one is not cold — and only a cold turn composes its system prompt. So a seat had its persona on its first turn of an episode and none on any turn after: no role, no team, no company, just the episode brief.
It still answered, which is why nothing complained. It simply was not being itself, from turn two onward, in every multi-turn episode.
EpisodeHost::personagives a host somewhere to hand the standing prompt back from, and the seeded history carries it at the head, where the turn reads it as the system message it would otherwise have composed.Related issue
None.
API or behavior changes
One new trait method on
EpisodeHost:Defaulted, so every existing host compiles and behaves exactly as before. A host that implements it gets the prompt back on its seeded turns.
Not breaking.
Validation
Commands actually run, with their outcome:
cargo fmt --all -- --check— passescargo clippy --all-targets --all-features -- -D warnings— not runcargo build --all-targets --all-features— not runcargo test --all-features— not runThe three unticked commands need this repository's own
vendor/openhuman, which is uninitialised in the checkout I worked from, so I did not run them rather than claim them. CI covers them.The change was verified end to end downstream in OpenCompany, which implements
EpisodeHost. Before it, roughly half of all seat turns arrived with no system message at all; after it, none do. An episode carrying an agent-to-agent conversation previously ran sixty seconds into the turn wall without concluding, and now finishes in just over one second.Tests
None added here. The behaviour needs a host that supplies a persona and a seat taking a second turn, which this repository has no fixture for — its own runners do not implement the new method. A test that exercises the seeding path properly is worth doing and I would rather it were deliberate work than something bolted onto this fix.
Documentation
The trait method carries the explanation: why a seeded turn is warm, why only a cold turn composes its prompt, and why the insert is conditional on there being history to seed.
Checklist
#[allow(...)],#[ignore], or relaxed lints.envcontents in the diff or the description🤖 Generated with Claude Code
Summary by CodeRabbit