Skip to content

[fix] Keep reference families and propose session names from the runner - #5992

Merged
mmabrouk merged 1 commit into
release/v0.112.1from
fix/runner-typed-session-references
Aug 12, 2026
Merged

[fix] Keep reference families and propose session names from the runner#5992
mmabrouk merged 1 commit into
release/v0.112.1from
fix/runner-typed-session-references

Conversation

@mmabrouk

@mmabrouk mmabrouk commented Aug 12, 2026

Copy link
Copy Markdown
Member

Context

This is the second PR of the untitled-sessions stack. It sits on top of #5991.

What the user sees. Clicking a session row sometimes goes nowhere. The link points at a route that does not exist.

Why it happens. The runner creates the session row for every headless run. It stored references that carried no label.

A "reference" is a pointer to a stored entity, such as {"id": "..."}. A run has three of them: the workflow, its variant and its revision. buildWorkflowReferences builds them as a map with those three names as keys. The old code then serialized the map with Object.values(...), which throws the keys away. The stored list held three bare ids and nothing that says which is which.

So the frontend had to guess. It treated the first UUID as the agent. Sometimes that UUID was a variant id, and a variant id is a dead route.

Changes

Each reference keeps its family name

Every serialized reference element now carries a key.

Look at the reference list the runner sends for one run.

Before:

[{"id": "wf-1"}, {"id": "var-1"}, {"id": "rev-1"}]

After:

[{"id": "wf-1", "key": "workflow"}, {"id": "var-1", "key": "workflow_variant"}, {"id": "rev-1", "key": "workflow_revision"}]

The heartbeat proposes a session name

The heartbeat is the periodic call the runner makes to the API to say a run is still alive.

A new function, proposeSessionName(request), builds a title. It takes the first user message that has text. It joins that message's text parts, trims the result, and cuts it to 60 Unicode code points. It counts code points rather than UTF-16 units, so it never splits an emoji in half. It proposes nothing when the input carries only attachments.

The proposal and the run's typed references ride every heartbeat, including the final beat that releases the session. The API from #5991 fills each field only while the stored value is NULL. So a repeat is a no-op, and a rename always wins.

One difference between the two writers is on purpose. The API's browser path reads the first user message only, which matches what the browser does. The runner instead skips ahead to the first message that has text. Fill-once makes the two work together: a session whose first message is an image still gets a title from its first readable message.

Tests

  • pnpm run typecheck is clean.
  • 2,144 unit tests, 8 integration tests and 18 acceptance tests pass.
  • 12 new unit tests cover proposeSessionName and the typed serialization. One of them checks the code-point cut on a string that ends in an emoji.
  • The live QA run in [fix] Fill session titles server-side and persist complete workflow references #5991 exercised this end to end. The heartbeat created the row with the proposed name and the keyed references.

@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Aug 12, 2026
@vercel

vercel Bot commented Aug 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agenta-documentation Error Error Aug 12, 2026 7:56pm

Request Review

@dosubot dosubot Bot added the backend label Aug 12, 2026
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 3b0aadeb-dd2a-42d7-90aa-62eb38e36de7

📥 Commits

Reviewing files that changed from the base of the PR and between deb3f69 and 4075881.

📒 Files selected for processing (7)
  • services/runner/src/engines/sandbox_agent/run-turn.ts
  • services/runner/src/engines/sandbox_agent/session-continuity-durable.ts
  • services/runner/src/server.ts
  • services/runner/src/sessions/alive.ts
  • services/runner/src/sessions/interactions.ts
  • services/runner/src/sessions/name.ts
  • services/runner/tests/unit/session-proposal.test.ts

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Sessions can now receive an automatically suggested name based on the first readable user message.
    • Session activity can include associated workflow, variant, and revision references for improved continuity and context.
    • Workflow references retain their specific type when shared across session interactions.
  • Bug Fixes

    • Improved handling of partial or missing workflow information.
    • Preserved compatibility with existing session records that lack newer reference details.
  • Tests

    • Added coverage for naming, reference handling, Unicode text, and session heartbeat updates.

Walkthrough

The runner now derives session names from readable user messages and serializes typed workflow references. It sends these values through all alive-watchdog heartbeats and stores typed references in session-turn ledger entries.

Changes

Session proposals and workflow references

Layer / File(s) Summary
Workflow reference contracts and serialization
services/runner/src/sessions/interactions.ts, services/runner/src/engines/sandbox_agent/session-continuity-durable.ts
Defines shared workflow identity and typed reference contracts. buildWorkflowReferenceList preserves workflow, variant, and revision keys. TurnReference accepts optional keys for older rows.
Session proposal and heartbeat flow
services/runner/src/sessions/name.ts, services/runner/src/sessions/alive.ts, services/runner/src/server.ts, services/runner/tests/unit/session-proposal.test.ts
Derives a trimmed, Unicode-safe session name from the first readable user message. The watchdog sends the optional name and typed references on initial, periodic, and release heartbeats. Tests cover names, references, and payload omission.
Turn ledger reference integration
services/runner/src/engines/sandbox_agent/run-turn.ts
Uses buildWorkflowReferenceList and passes the resulting typed list directly to session-turn ledger entries.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant server_ts
  participant proposeSessionName
  participant buildWorkflowReferenceList
  participant startAliveWatchdog
  participant sendHeartbeat
  participant SessionHeartbeatEndpoint
  server_ts->>proposeSessionName: derive session name from AgentRunRequest
  server_ts->>buildWorkflowReferenceList: build typed workflow references
  server_ts->>startAliveWatchdog: pass SessionProposal
  startAliveWatchdog->>sendHeartbeat: forward proposal
  sendHeartbeat->>SessionHeartbeatEndpoint: send name and references
Loading

Possibly related PRs

  • Agenta-AI/agenta#5156: Introduces the session keep-alive and server session lifecycle used by these heartbeat changes.
  • Agenta-AI/agenta#5369: Reorganizes the sandbox-agent and session APIs updated by this change.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 60.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes both primary changes: preserving reference families and proposing session names in the runner.
Description check ✅ Passed The description directly explains the reference serialization fix, session name proposals, heartbeat behavior, and supporting tests.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/runner-typed-session-references

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Railway Preview Environment

Status Destroyed (PR closed)

Updated at 2026-08-12T20:10:27.373Z

@mmabrouk mmabrouk left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inline notes to explain the intent behind each part of this change. They are explanations for the reviewer, not change requests.

return Array.from(text).slice(0, NAME_MAX_CODE_POINTS).join("");
}
return undefined;
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This picks the title for a session that no browser will ever render.

It takes the first user message that HAS text, not simply the first user message. A run can start with an image or an attachment, and titling from that would produce an empty string.

The cut counts code points, not UTF-16 units. A plain slice can split a surrogate pair and leave half an emoji at the end of the title.

When no message carries readable text, the function returns undefined and proposes nothing. An untitled session is better than one titled with an empty string.

...reference,
key: key as ReferenceKey,
}));
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the fix for the dead-route half of the bug.

buildWorkflowReferences returns a map keyed by family: workflow, workflow_variant, workflow_revision. Every persisted shape (the turn append, the heartbeat) stores a flat list instead. The old code serialized that map with Object.values(...), which drops the keys and leaves the reader with three bare uuids.

This builder keeps each element's key, so a reader can tell the workflow from its variant instead of guessing.

Comment thread services/runner/src/sessions/interactions.ts
Comment thread services/runner/src/sessions/alive.ts
Comment thread services/runner/src/sessions/alive.ts
name: proposeSessionName(request),
references: buildWorkflowReferenceList(request.runContext?.workflow),
},
);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where the two proposals get attached to the run.

The name matters because the browser is the only other title writer, and no browser renders a headless run. The references matter because today they ride only on a fire-and-forget turn append, so a dropped append leaves a row the UI cannot open. The heartbeat happens on every run, which is why both facts travel with it.

@mmabrouk

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@mmabrouk
mmabrouk force-pushed the fix/sessions-headless-title-and-references branch from deb3f69 to c361a2a Compare August 12, 2026 19:36
@mmabrouk
mmabrouk force-pushed the fix/runner-typed-session-references branch from 4075881 to 3439b9e Compare August 12, 2026 19:36

@mmabrouk mmabrouk left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@mmabrouk mmabrouk added the lgtm This PR has been approved by a maintainer label Aug 12, 2026
… heartbeat

The turn ledger no longer drops the workflow reference family keys (Object.values): every serialized reference element now carries key = workflow | workflow_variant | workflow_revision. The session heartbeat additionally carries a proposed name (first user message with text, trimmed to 60 code points, surrogate-safe) and the run's typed references; the API fills both once, only while the stored values are NULL, so renames and browser titles always win.
@mmabrouk
mmabrouk force-pushed the fix/sessions-headless-title-and-references branch from c361a2a to c5f0362 Compare August 12, 2026 19:56
@mmabrouk
mmabrouk force-pushed the fix/runner-typed-session-references branch from 3439b9e to 06477eb Compare August 12, 2026 19:56
@mmabrouk
mmabrouk changed the base branch from fix/sessions-headless-title-and-references to release/v0.112.1 August 12, 2026 20:09
@mmabrouk
mmabrouk merged commit 3e73ed3 into release/v0.112.1 Aug 12, 2026
52 of 60 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend lgtm This PR has been approved by a maintainer size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant