Skip to content

feat(api): record who started each thread, and list them in the web client - #184

Merged
ciaransweet merged 1 commit into
mainfrom
feat/thread-owner
Oct 13, 2026
Merged

ciaransweet merged 1 commit into
mainfrom
feat/thread-owner

Conversation

@ciaransweet

@ciaransweet ciaransweet commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Adds an owner hook to create_router and create_app: a function from the request to an opaque identifier, or None.

  • The first run on a thread records the caller under owner in its checkpoints' metadata. Later runs leave it unchanged, so the owner is whoever sent the first message.
  • GET /threads lists the caller's threads, newest first, each with its first question and start time. It is added only with the hook, and answers 403 for a caller with no identity.
  • No identity is recorded as "", because LangGraph drops None from run metadata. A thread from before the hook has no owner key.
  • Nothing is enforced: a thread is still readable by whoever holds its id.
  • No schema change. On Postgres the listing scans checkpoints; a GIN index on metadata is the fix if that becomes slow.
  • The bundled web client lists the threads in a collapsible column on the right, and opens one on click. Without the hook, or for a caller with no identity, there is no column.

Tested against InMemorySaver and a real Postgres (MCP_AGENT_TEST_POSTGRES), and the web client locally against dss with an accounts-test sign-in.

image image

🤖 Generated with Claude Code

@ciaransweet ciaransweet changed the title feat(api): record who started each thread, and list a caller's own threads feat(api): record who started each thread, and list them in the web client Oct 7, 2026
…lient

create_router and create_app take an `owner` hook: a function from the
request to an opaque identifier, or None. The first run on a thread puts
it on the checkpoints' metadata under `owner`; later runs leave it alone,
so the owner is whoever sent the first message. GET /threads lists the
caller's threads, newest first, with each one's first question and start
time, and refuses a caller with no identity.

No identity is recorded as "", because LangGraph drops None from run
metadata. Nothing is enforced yet, and nothing is added to the database:
the listing filters checkpoint metadata, which on Postgres scans the
checkpoints table.

The bundled web client lists those threads in a collapsible column on
the right, and opens one on click. Without the hook it draws no column.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@yellowcap yellowcap left a comment

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.

Its my thread! 😆 ! Looks good, thanks @ciaransweet !

@ciaransweet
ciaransweet merged commit d076d88 into main Oct 13, 2026
4 checks passed
@ciaransweet
ciaransweet deleted the feat/thread-owner branch October 13, 2026 11:29
ciaransweet pushed a commit that referenced this pull request Oct 13, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.10.6](mcp-toolsets-runtime-v0.10.5...mcp-toolsets-runtime-v0.10.6)
(2026-10-13)


### Features

* **api:** record who started each thread, and list them in the web
client
([#184](#184))
([d076d88](d076d88))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: ds-release-bot[bot] <116609932+ds-release-bot[bot]@users.noreply.github.com>
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