Skip to content

agent threads: shared partitions, exact task states, and durable call metadata - #1885

Merged
theomonnom merged 16 commits into
mainfrom
theo/thread-schema-v2
Nov 15, 2026
Merged

theomonnom merged 16 commits into
mainfrom
theo/thread-schema-v2

Conversation

@theomonnom

@theomonnom theomonnom commented Oct 23, 2026 •

Copy link
Copy Markdown
Member

Agents 2.0 needs text and voice endpoints to share a durable conversation partition, preserve every task state, and restore the metadata that approvals and pending tool/delegation calls depend on. This PR updates those contracts together and incorporates #1924.

Changes:

  • Keep schema version 1 and ThreadSchemaV1, replacing lanes with explicit, non-empty partition keys. DefaultPartitionKey supplies the framework default.
  • Preserve conversation order separately from insertion pagination; add nullable task message links, endpoint destinations, journal retry identities, and indexes for task acceptance, update-time listings, and terminal run receipts.
  • Store persisted timestamps and lease expiry as integer Unix milliseconds. Remove the cross-worker interruption marker from partition ownership.
  • Expose all seven task states through the existing typed status enum and filter. Preserve numeric values; rename RUNNING to WORKING at 1 and append SUBMITTED, INPUT_REQUIRED and REJECTED at 5–7. Preserve absent versus explicitly empty task names.
  • Restore FunctionCall.extra as map<string,string> on new field 7. Each value is JSON text, so strings, structured delegation state, approval identities, provider data, and application receipts survive serialization. Readers can accept non-JSON legacy values as plain strings. Keep incompatible field number 6 reserved.
  • Regenerate Go bindings and include changesets for Go and JavaScript packages.

Compatibility and rollout:
The v1 SQL schema changes in place without migration; framework and platform consumers must update together. Public-api-server needs regenerated OpenAPI, and agent-db must retain unnamed tasks and exact task states. The changed JSON enum name requires consumer updates. New tag 7 protects the protobuf field-number contract; older Python exporters that copy fields by name still require the corrected serializer when using this updated schema. Existing typed chat payloads are retained; lossless image/audio persistence is outside this PR.

Validation:
GOWORK=off go test ./livekit/agent passes, including exact task-state/filter mappings, optional label presence, JSON/binary function-call metadata round trips, and a regression ensuring legacy field 6 is not interpreted as the metadata map. The combined schema was previously exercised by the agents-v2 storage suite (154 passed, 32 ignored). The Rust SDK cascade and refreshed v2 pin are tracked in livekit/rust-sdks#1679; its source now follows this consolidated protocol PR rather than retaining the old extra-field snapshot.

This PR targets protocol main. #1924 was merged into this branch, not independently into main.

@changeset-bot

changeset-bot Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2796fd1

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
github.com/livekit/protocol Patch
@livekit/protocol Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@theomonnom theomonnom changed the title agent threads: schema version 2 for A2A v1 agent threads: simplify v1 storage with partition keys Nov 10, 2026
theomonnom and others added 3 commits November 14, 2026 20:05
…#1924)

* Update module github.com/go-jose/go-jose/v4 to v4.1.5 (#1809)

Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* Add api_key to StartSession for session/key correlation (#1886)

Carries the API key that issued the join token from the controller to the
media node, so RTC session logs can be correlated with the issuing key.

Co-authored-by: Claude Opus 4.8 <[email protected]>

* metrics: add session_summary to MetricsRecordingHeader (#1884)

Co-authored-by: Claude Opus 5.5 <[email protected]>

* agent: add CloseReason enum for agent session close reasons (#1887)

* agent: add CloseReason enum for agent session close reasons

Agent evals read the session's close reason from the recording upload's session summary;
the enum keeps the value names the same across the Python, JS and Go code.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Update protobufs/agent/livekit_agent_session.proto

Co-authored-by: Théo Monnom <[email protected]>

* generated protobuf

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Théo Monnom <[email protected]>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>

* Add NodeStats.forward_scheduling_delay (#1891)

* Add NodeStats.forward_scheduling_delay

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* generated protobuf

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>

* add job details in `MigrateJobRequest` to track jobs after reconnect (#1893)

* Version Packages (#1875)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Replace NodeStats forward_scheduling_delay with processing per subscriber (#1895)

* Replace NodeStats forward_scheduling_delay with forward_processing_per_subscriber

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* generated protobuf

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>

* Add SIPDialtone enum and deprecate play_dialtone (#1892)

* Add SIPDialtone enum and deprecate play_dialtone

Lets callers pick a regional dial tone preset on CreateSIPParticipant
and TransferSIPParticipant. play_dialtone still maps to the ETSI tone
when the enum is unset, and is kept populated for older sip services.

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>

* Rename NodeStats forward_processing_per_subscriber to forward_processing_per_write (#1897)

* Rename NodeStats forward_processing_per_subscriber to forward_processing_per_write

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* generated protobuf

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>

* agent_simulation: dial a phone number over SIP instead of dispatching an agent (#1858)

* agent_simulation: dial a phone number over SIP instead of dispatching an agent

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>

* feat(sdp): add CodecsFromSessionDescription and ParseFmtp (#1899)

* hwstats: add WithHostCPU option to measure whole-host CPU (#1903)

Co-authored-by: Claude Opus 5.5 <[email protected]>

* hwstats: ignore the CPU request override with WithHostCPU (#1904)

Co-authored-by: Claude Opus 5.5 <[email protected]>

* webhook: wait for queued events when draining ResourceURLNotifier (#1901)

Stop(false) asked the resource queues to drain but returned straight away,
so a caller that exits after Stop lost the events still queued. Wait for
the queues to finish, as URLNotifier.Stop(false) does.

* SIP authentication: compare IP masks against remote address rather than From header. (#1889)

* sip: add SIPMediaConfig.drop_audio_during_dtmf (#1907)

* Update pion deps (#1810)

Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* Update module github.com/prometheus/procfs to v0.22.0 (#1812)

Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* logger: drop dead nil checks flagged by staticcheck SA4023 (#1909)

protoreflect.Message.Get never returns a nil List or Map for repeated or
map fields; unset fields yield an empty read-only value. The nil
comparisons in protoFieldIsZero were never true, and newer staticcheck
reports them.

Co-authored-by: Claude Opus 5.5 <[email protected]>

* Update module github.com/go-jose/go-jose/v4 to v4.1.6 [SECURITY] (#1908)

Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* build: move pnpm settings to pnpm-workspace.yaml (#1910)

pnpm 11+ no longer reads the "pnpm" field in package.json, so overrides
and the esbuild build-script allowance were silently dropped and
`pnpm install` failed with ERR_PNPM_IGNORED_BUILDS. Move both into
pnpm-workspace.yaml, using allowBuilds, which pnpm 10 and 12 both honor.

Give protobuf-es and TypeScript majors their own Renovate PRs: both need
dedicated migration work and would otherwise block the grouped npm bump.

Co-authored-by: Claude Opus 5.5 <[email protected]>

* Update github workflows (#1774)

Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* Update npm deps (#975)

Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* Update github.com/petermattis/goid digest to abfca07 (#1890)

Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* Update dependency typescript to v7 (#1917)

Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* Update module go.opentelemetry.io/otel to v1.47.0 (#1916)

Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* Update module github.com/prometheus/client_golang to v1.25.0 (#1914)

Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* Update module github.com/maxbrunsfeld/counterfeiter/v6 to v6.14.0 (#1913)

Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* Update module github.com/gammazero/deque to v1.2.2 (#1912)

Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* Update golang.org/x/exp digest to f0251eb (#1911)

Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* auth: fix VideoGrant permission doc to match actual defaults (#1918)

The comment claimed an all-or-nothing default. In fact each of CanPublish,
CanSubscribe and CanPublishData defaults to granted when left unset, evaluated
independently, and CanPublishData falls back to the effective CanPublish value.

Co-authored-by: Claude Opus 4.8 <[email protected]>

* Preserve A2A task states and optional labels in thread listings

The four-state view collapsed pending questions into running and rejected tasks into
failed. Keep the framework's exact status string and label presence through the generated
thread records; state filters select only the requested outcome.

* Test task label presence through protobuf JSON

* generated protobuf

* Test task label presence through protobuf JSON

* Fix merged test imports

* Keep task statuses typed with all seven framework states

* generated protobuf

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Raja Subramanian <[email protected]>
Co-authored-by: Claude Opus 4.8 <[email protected]>
Co-authored-by: Jake McClanahan <[email protected]>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: David Zhao <[email protected]>
Co-authored-by: Denys Smirnov <[email protected]>
Co-authored-by: u9g <[email protected]>
Co-authored-by: Anunay Maheshwari <[email protected]>
Co-authored-by: Martin Njalale <[email protected]>
Co-authored-by: Alex Fish <[email protected]>
Co-authored-by: Alex <[email protected]>
Co-authored-by: Benjamin Pracht <[email protected]>
@theomonnom theomonnom changed the title agent threads: simplify v1 storage with partition keys agent threads: partition-keyed v1 storage and exact task states Nov 15, 2026
@theomonnom theomonnom changed the title agent threads: partition-keyed v1 storage and exact task states agent threads: shared partitions, exact task states, and durable call metadata Nov 15, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: pretty wordy, would be good to shorten

@theomonnom
theomonnom merged commit ef439e9 into main Nov 15, 2026
9 checks passed
@theomonnom
theomonnom deleted the theo/thread-schema-v2 branch November 15, 2026 04:59
@github-actions github-actions Bot mentioned this pull request Nov 15, 2026
theomonnom added a commit to livekit/rust-sdks that referenced this pull request Nov 15, 2026
Agents 2.0 needs a reusable HTTP client, the shared thread-persistence
schema, exact task states, and durable function-call metadata. This PR
supplies the SDK side and supersedes #1652.

Changes:

- Add `LiveKitApi::with_api_key_and_client`. Every service and failover
region discovery reuse the supplied TLS/proxy configuration and
connection pool; discovery keeps its short timeout.
- Expose `agent::DEFAULT_PARTITION_KEY` and pin the consolidated
partition-keyed v1 schema from livekit/protocol#1885.
- Preserve all seven typed task states, optional task-name presence, and
exact status filters.
- Restore `FunctionCall.extra` on protobuf tag 7, with JSON text per
value for approvals, resumable tool/delegation state, provider metadata,
and application receipts. Legacy tag 6 remains reserved.
- Regenerate protocol/serde bindings, normalize trailing whitespace in
generated serde output, and include patch changesets for affected
packages and dependents.

Dependency and compatibility:

The protocol submodule pins protocol-main commit
`ef439e910d5c14f591de70a29899c62415ec8e84`, which landed
livekit/protocol#1885 (including #1924). Its tree is identical to the
tested protocol PR head. The temporary integration snapshot is no longer
needed.

The SQL schema changes in place at version 1 and requires coordinated
platform/framework consumers. Task JSON RUNNING becomes WORKING.
Metadata uses a fresh wire number; older Python exporters that copy
fields by name still need their corrected serializer. The companion
agents-v2 working tree now pins SDK commit
`09e0a8e4334cf53529b521381aaf07f1e880a212`; its status adapters, SQLite
record and newer protocol adapters were updated locally. Those v2 edits
are outside this SDK PR.

Validation:

- Protocol Go tests and protocol CI pass, including metadata JSON/binary
round trips, legacy tag isolation, and the repository's protojson import
policy.
- SDK protocol tests pass (2 tests), and the API crate check passes with
services/rustls features. The API regression suite previously passed 32
tests; external mock-server cases return early locally when its server
is unavailable, while loopback tests execute locally.
- In v2, the Python extension/FFmpeg build and all-target Rust workspace
check pass. The full Rust workspace suite and Python binding contracts
pass, including 113 embedded Python binding tests.
- Hermetic Python host/plugin/smoke suites: 2,900 passed, 63 skipped, 66
expected xfails.
- Rust formatting, Clippy policies, architecture checks and
generated-code checks pass. Python formatting, lint, strict mypy and
pyright pass (pyright reports 2 existing warnings).
- The final pin now points to the protocol-main merge commit. Its tree
is identical to the tested protocol PR revision; no generated Rust
source changed in this final update.

The tests used an isolated Cargo target. A disk-space linker failure was
resolved by removing this session's temporary build caches; the binding
suite then passed. Live voice E2E was not run: no LiveKit project
credentials or local livekit-server are configured. No wheel release or
live-room behavior is claimed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants