Skip to content

feat(sdk): chat sessions accept concurrencyKey and trigger-time named limits - #4906

Closed
matt-aitken wants to merge 8 commits into
docs/queue-concurrency-featuresfrom
feat/chat-session-concurrency
Closed

matt-aitken wants to merge 8 commits into
docs/queue-concurrency-featuresfrom
feat/chat-session-concurrency

Conversation

@matt-aitken

Copy link
Copy Markdown
Member

Summary

Stacked on #4853. Chat agents already accept the task-level concurrency option, but the session trigger path had no way to scope runs per chat or tenant. Session trigger config now carries concurrencyKey and up to two trigger-time named limits, so a chat agent declaring concurrency: { perKey: 1 } can actually get one run per tenant by passing a key when the session starts:

const start = chat.createStartSessionAction("support-chat", {
  triggerConfig: { concurrencyKey: user.id },
});

Design

The two fields ride the existing session trigger config, so every run the session schedules (initial, continuation, and upgrade re-triggers) carries them through one choke point on the server. All three session starters forward them: chat.createStartSessionAction, the browser AgentChat client, and handover. Named limits are validated client-side with the same rules and error messages as tasks.trigger.

The key is never defaulted from the chat ID: a session without an explicit concurrencyKey shares the task's keyless pool, so existing chat agents keep their current concurrency accounting.

@changeset-bot

changeset-bot Bot commented Sep 7, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: d511299

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

This PR includes changesets to release 27 packages
Name Type
@trigger.dev/sdk Patch
@trigger.dev/core Patch
@trigger.dev/python Patch
@internal/dashboard-agent Patch
@trigger.dev/build Patch
trigger.dev Patch
@trigger.dev/redis-worker Patch
@trigger.dev/schema-to-json Patch
@internal/clickhouse Patch
@internal/llm-model-catalog Patch
@internal/metrics-pipeline Patch
@trigger.dev/rbac Patch
@internal/redis Patch
@internal/replication Patch
@internal/run-engine Patch
@internal/run-store Patch
@internal/schedule-engine Patch
@internal/tracing Patch
@internal/webhook-engine Patch
@internal/webhook-sources Patch
@internal/cache Patch
@trigger.dev/react-hooks Patch
@trigger.dev/rsc Patch
@trigger.dev/database Patch
@trigger.dev/otlp-importer Patch
@trigger.dev/sso Patch
@internal/testcontainers 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

@coderabbitai

coderabbitai Bot commented Sep 7, 2026 •

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

The change adds shared validation for named concurrency limits and adds concurrency and concurrencyKey to SessionTriggerConfig. Chat session start actions and AgentChat forward these values, with per-call values taking precedence. Webhook delivery validates configuration only for new sessions. Triggered runs receive the configured values. Tests and documentation cover precedence, omission, clearing, and invalid names.

Priority: ⬇️ Low

Merge Risk: 🟡 Moderate · up to dfe4e

When two requests both start the same chat session at nearly the same time, whichever request's configuration loses the race can silently override the intended per-session concurrency limits or key, so the session may not get the concurrency scoping the caller expects. This should be fixed with a create-if-absent write before merging, though it is a narrow timing window rather than a broad outage risk.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the change and its design, but it omits the required issue reference, checklist, testing details, changelog section, and screenshots section. Add the required template sections. Include a Closes # reference, complete the checklist, describe testing performed, add a short changelog entry, and address screenshots or mark them as not applicable.
Docstring Coverage ⚠️ Warning Docstring coverage is 55.56% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 9 functions across 9 files. (2 skipped: 2… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: support for concurrencyKey and trigger-time named limits in chat sessions.
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.
Full details: Docstring Coverage

Explanation

Docstring coverage is 55.56% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 9 functions across 9 files. (2 skipped: 2 unsupported.)

✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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.

devin-ai-integration[bot]

This comment was marked as resolved.

@pkg-pr-new

pkg-pr-new Bot commented Sep 7, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

@trigger.dev/build

npm i https://pkg.pr.new/@trigger.dev/build@d511299

trigger.dev

npm i https://pkg.pr.new/trigger.dev@d511299

@trigger.dev/core

npm i https://pkg.pr.new/@trigger.dev/core@d511299

@trigger.dev/python

npm i https://pkg.pr.new/@trigger.dev/python@d511299

@trigger.dev/react-hooks

npm i https://pkg.pr.new/@trigger.dev/react-hooks@d511299

@trigger.dev/redis-worker

npm i https://pkg.pr.new/@trigger.dev/redis-worker@d511299

@trigger.dev/rsc

npm i https://pkg.pr.new/@trigger.dev/rsc@d511299

@trigger.dev/schema-to-json

npm i https://pkg.pr.new/@trigger.dev/schema-to-json@d511299

@trigger.dev/sdk

npm i https://pkg.pr.new/@trigger.dev/sdk@d511299

commit: d511299

@matt-aitken
matt-aitken force-pushed the feat/chat-session-concurrency branch from e827c3a to 1dbb27b Compare September 7, 2026 13:14
@matt-aitken
matt-aitken force-pushed the feat/chat-session-concurrency branch from d126a77 to 12e74ba Compare September 7, 2026 17:26
@matt-aitken
matt-aitken force-pushed the feat/chat-session-concurrency branch from 12e74ba to 26e870e Compare September 7, 2026 17:28
@matt-aitken
matt-aitken force-pushed the feat/chat-session-concurrency branch from 26e870e to eae339e Compare September 7, 2026 17:34
@matt-aitken
matt-aitken force-pushed the feat/chat-session-concurrency branch from eae339e to 1f029e0 Compare September 7, 2026 17:42
@matt-aitken
matt-aitken force-pushed the feat/chat-session-concurrency branch from 1f029e0 to 723efdb Compare September 7, 2026 17:58
@matt-aitken
matt-aitken force-pushed the feat/chat-session-concurrency branch from 723efdb to 6fc3aca Compare September 7, 2026 17:59
@matt-aitken
matt-aitken force-pushed the feat/chat-session-concurrency branch from 6fc3aca to 783acbb Compare September 7, 2026 18:04
@matt-aitken
matt-aitken force-pushed the feat/chat-session-concurrency branch from 783acbb to 58ec45f Compare September 7, 2026 18:12
@matt-aitken
matt-aitken force-pushed the feat/chat-session-concurrency branch from 58ec45f to 3d315ae Compare September 7, 2026 18:14
@matt-aitken
matt-aitken force-pushed the feat/chat-session-concurrency branch from 3d315ae to f9ea87f Compare September 7, 2026 18:24
@matt-aitken
matt-aitken force-pushed the feat/chat-session-concurrency branch from f9ea87f to b900600 Compare September 8, 2026 09:26
@matt-aitken
matt-aitken force-pushed the feat/chat-session-concurrency branch from b900600 to 6a02ae6 Compare September 8, 2026 09:27
coderabbitai[bot]

This comment was marked as resolved.

@matt-aitken
matt-aitken force-pushed the feat/chat-session-concurrency branch from c5fa7ea to 534623e Compare September 17, 2026 12:46
@matt-aitken
matt-aitken force-pushed the feat/chat-session-concurrency branch from 534623e to dfe4e61 Compare September 17, 2026 12:56
coderabbitai[bot]

This comment was marked as resolved.

@matt-aitken
matt-aitken force-pushed the feat/chat-session-concurrency branch from c6c49c0 to 856e0e8 Compare September 17, 2026 14:06
@matt-aitken
matt-aitken force-pushed the feat/chat-session-concurrency branch from 856e0e8 to 19cb375 Compare September 17, 2026 14:19
@matt-aitken
matt-aitken force-pushed the feat/chat-session-concurrency branch from 19cb375 to 94c9edf Compare September 17, 2026 14:28
@matt-aitken
matt-aitken force-pushed the feat/chat-session-concurrency branch from 94c9edf to 173b8e2 Compare September 17, 2026 15:09
@matt-aitken
matt-aitken force-pushed the feat/chat-session-concurrency branch from 173b8e2 to f27f13e Compare September 17, 2026 15:15
…r-time named limits

Chat agents already accept the task-level concurrency option, but the
session trigger path had no way to scope runs: SessionTriggerConfig now
carries concurrencyKey and up to two named limits, threaded through the
session run trigger (initial, continuation, and upgrade re-triggers) and
forwarded by all three session starters (createStartSessionAction, the
AgentChat client, and handover). Keys are never defaulted from the chat
ID; a session without one shares the task's keyless pool. Named limits
are validated client-side with the same rules as tasks.trigger.
…e module

triggerConcurrencyBody and validateConcurrencyLimitName move to a
dependency-free module so the chat-server route-handler entrypoint stays
lean instead of pulling the task runtime's import graph into customer
bundles.
…rsists

The session trigger config's concurrency names now carry the charset rule
in the schema itself, so an invalid name fails session creation instead of
poisoning a persisted, run-less session that fails every retry. The
AgentChat client validates through the same dependency-free helper as the
other starters, tests pin per-call concurrency precedence and the
empty-array clear, and the chat-server import allowlist names the new
module.
…ting

Webhook deliveries parse the assembled trigger config before creating the
session, failing terminally on a bad routing-target template instead of
persisting a session that every continuation re-parse would strand. The
trigger and batch bodies share the session config's limit-name rule (1-122
chars, letters/numbers/underscores/hyphens), so a bad name is a uniform
up-front 400 on every path rather than a late validation error after
earlier batch items already triggered.
…ever resumes

Template validation moves inside the create branch: resume deliveries to
existing sessions never touch the template, so editing a routing target to
an invalid template can't terminally fail events to healthy live sessions.
A non-object basePayload is rejected instead of being spread into
index-keyed garbage, and unknown template keys persist as before with only
the known fields normalized by the parse.
…y dropped

Truthiness guards at the trigger call sites swallowed falsey concurrency
values before validation, so a JavaScript caller passing an empty string or
null started the session without the intended limits. Only undefined counts
as absent now; everything else flows into validation and throws.
…ng the action default

Nullish coalescing treated a per-call null as unspecified, silently selecting
the action default (or skipping validation entirely when no default exists).
Per-call selection now treats only undefined as absent, matching the other
chat trigger surfaces.
@matt-aitken
matt-aitken force-pushed the feat/chat-session-concurrency branch from f27f13e to d511299 Compare September 17, 2026 15:20
@matt-aitken

Copy link
Copy Markdown
Member Author

Closing: this stack was flattened into a single change that has now been merged and will land in this repository via the automated sync. All review feedback from these PRs is incorporated, along with further review rounds on the flattened change.

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