Skip to content

feat(tangent): brief the agent on naming, and on the project its runs belong to - #2792

Draft
camielvs wants to merge 2 commits into
09-22-feat_projects_that_can_be_shared_and_cancelledfrom
09-23-feat_let_the_agent_name_the_project_and_session
Draft

camielvs wants to merge 2 commits into
09-22-feat_projects_that_can_be_shared_and_cancelledfrom
09-23-feat_let_the_agent_name_the_project_and_session

Conversation

@camielvs

@camielvs camielvs commented Sep 23, 2026

Copy link
Copy Markdown
Collaborator

Problem

A project opened from the dashboard prompt arrived as "Project 7", with a
session called "Session 1" and a pipeline named after the entire request —
Build a pipeline that scrapes wikipedia and converts articles into a pokemon….
Every one of those is a placeholder, and the agent reading the opening message
already knows what the work is about.

What changed

The agent names all three in its first turn, from the first message.
rename_project, name_session and name_pipeline are workarea tools, and a
naming brief is seeded into the session's memory before the agent spawns, so
it is context from turn one rather than something said in the transcript.

Only a name nobody chose may be replaced. A project or pipeline someone
named deliberately is left alone and the call answers { renamed: false }
which the brief tells the agent is a final answer, not something to retry. The
mark is dropped by whoever renames next, agent or human.

Naming a pipeline is the part with real plumbing behind it

set_pipeline_name used to rename the spec held in memory and nothing else, so
the agent reported success while the file stayed Draft and both resource lists
kept the name recorded when the pipeline was added.

The spec name is now canonical and everything follows it. The rename goes through
the file first, and the name the file actually took is what the spec is called —
a collision adjusts rather than overwriting, the rule create_pipeline already
follows, and the agent is told so:

Renamed to "Churn model 2" — "Churn model" was already taken.

The open tab retitles rather than announcing the name it resolved when it opened.

And the rename now invalidates the query behind the resource lists. Browser
storage fires no event a same-tab rename would reach, and that query is keyed on
the pointer, which a rename does not change. Without this the new name only
appeared a minute later, or on reload — which read as the rename silently
failing.

name_pipeline drives the open tab's bridge rather than the resource row,
because only the bridge moves the spec, the file and the row together. The editor
keeps a fallback rule for a pipeline still unnamed once its changes are in, and
the provisional mark lives on the spec rather than the resource because the agent
that acts on it reads the canvas and never sees the row.

Resource rows stop trusting a stale copy

Both lists ask what a pipeline is called now, which also fixes the same
staleness after a rename from the menu bar. A name-only pointer is trusted only
in the browser that wrote it — someone else's "Churn model" is not the one this
browser holds. Unknown authorship is trusted, which is every single-user backend.
useUnavailablePipelines moves to services/projects as useLocalPipelineStatus,
since both pages need it and it answers two questions rather than one.

This also meant separating a row's display label from "this row opens a
conversation elsewhere", which had been sharing one prop. A renamed pipeline is
still a row on this page; overloading the label would have made it open as a
session and lose its Remove button.

A derived name also keeps what the ask was about: trimming a dangling preposition
off the end must not amputate the subject with it.

The same seed now tells the agent which project its runs belong to

A run reaches a project's feed by carrying an annotation naming the project,
written at submit time — there is no run row to attach afterwards, and the key
cannot be added later, because the endpoint that sets a single annotation takes
the key as a path segment and rejects this one for its slashes.

A run submitted from the browser is attributed already: the scope provider puts
the annotation in the submission. An agent submitting from its own sandbox is
not, and cannot be
— the remote-env handshake carries only the session id, and
the workarea tools submit no runs. So the id never reaches the agent that needs
it, and a run it starts is filed under nothing. That is what was seen on staging:
the agent fell back to building a pipeline outside the canvas, submitted it
itself, and the project reported nothing had been run.

The memory seed already briefs the agent before it spawns, so the project id goes
there, with the annotation to submit with and the two limits it would otherwise
discover by being refused: one project per run, and never this key on a saved
pipeline, whose stored annotations decide its version identity.

The key is built from the same helper the browser submits with, so the two
cannot drift.

This makes the agent aware; it does not make it certain. A brief can be
forgotten on a later turn, and a forgotten tag cannot be repaired. The guarantee
would be for the sandbox's own submit helper to add the annotation from session
context — which needs the id on the wire, and that half is not in this repo.

Note on scope

This absorbs what was PR #2796. Split apart, this PR claimed to name pipelines
while the rename only ever reached the spec in memory — they are one change.

Run attribution rides along because it is the same artifact: one memory seed,
written once before the agent spawns. A second PR would have been a second edit
to the same string.

Testing

  • pnpm run validate clean; npx vitest run 320 files / 3248 tests green.
  • Observed against a live agent: project and session named from the opening
    message; the pipeline rename fired and the collision message surfaced, but the
    new name only reached the lists on reload — which the query invalidation here
    fixes. The first-turn name_pipeline path has not been exercised against a
    live agent yet.

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Sep 23, 2026

Copy link
Copy Markdown

🎩 Preview

A preview build has been created at: 09-23-feat_let_the_agent_name_the_project_and_session/d63dfbd

camielvs commented Sep 23, 2026

Copy link
Copy Markdown
Collaborator Author

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

@camielvs
camielvs force-pushed the 09-23-feat_let_the_agent_name_the_project_and_session branch from 30b3481 to feba6da Compare September 23, 2026 20:57
@camielvs
camielvs force-pushed the 09-23-feat_let_the_agent_name_the_project_and_session branch from feba6da to 54a9c09 Compare September 23, 2026 21:54
@camielvs
camielvs force-pushed the 09-22-feat_projects_that_can_be_shared_and_cancelled branch from 0847afe to 817fb36 Compare September 23, 2026 22:01
@camielvs
camielvs force-pushed the 09-23-feat_let_the_agent_name_the_project_and_session branch from 54a9c09 to 37ebe50 Compare September 23, 2026 22:02
@camielvs
camielvs force-pushed the 09-22-feat_projects_that_can_be_shared_and_cancelled branch from 817fb36 to cbd78d9 Compare September 23, 2026 23:00
@camielvs
camielvs force-pushed the 09-23-feat_let_the_agent_name_the_project_and_session branch 2 times, most recently from 44b87c5 to 637f724 Compare September 23, 2026 23:36
@camielvs
camielvs force-pushed the 09-22-feat_projects_that_can_be_shared_and_cancelled branch from cbd78d9 to 37c0312 Compare September 23, 2026 23:36
@camielvs
camielvs force-pushed the 09-23-feat_let_the_agent_name_the_project_and_session branch from 637f724 to 49c87b1 Compare September 23, 2026 23:56
@camielvs
camielvs force-pushed the 09-22-feat_projects_that_can_be_shared_and_cancelled branch from 37c0312 to 74c9c32 Compare September 23, 2026 23:56
A project opened from the dashboard prompt arrived as "Project 7" with a
session called "Session 1" and a pipeline named after the whole request.
Every one of those is a placeholder, and the agent reading the opening
message already knows what the work is about.

The agent now names all three in its first turn, from the first message.
`rename_project`, `name_session` and `name_pipeline` are workarea tools,
and a naming brief is seeded into the session's memory before the agent
spawns, so it is context from the first turn rather than something said
in the transcript.

A name nobody chose is marked as such, and only a marked name may be
replaced: a project or pipeline someone named deliberately is left alone
and the call answers `{ renamed: false }`, which the brief tells the
agent is a final answer rather than something to retry. The mark is
dropped by whoever renames next, agent or human.

Naming a pipeline is the part with real plumbing behind it.
`set_pipeline_name` used to rename the spec held in memory and nothing
else, so the agent reported success while the file stayed "Draft" and
both resource lists kept the name recorded when the pipeline was added.
The spec name is now canonical and everything follows it: the rename goes
through the file first, and the name the file actually took is what the
spec is called — a name already taken comes back adjusted, and the agent
is told so rather than left believing it got the name it asked for. The
open tab retitles instead of announcing the name it had when it opened.

Browser storage fires no event a rename in this tab would reach, and the
query behind those lists is keyed on the pointer, which a rename does not
change — so the rename invalidates it. Without that the new name only
appeared a minute later, or on reload, which read as a silent failure.

`name_pipeline` drives the open tab's bridge rather than the resource
row, because only the bridge moves the spec, the file and the row
together. The editor keeps a fallback rule for a pipeline still unnamed
once its changes are in, and the provisional mark lives on the spec
rather than the resource because the agent that acts on it reads the
canvas and never sees the row.

Both resource lists now ask what a pipeline is called rather than
trusting the copy on the row, which also fixes the same staleness after a
rename from the menu bar. A name-only pointer is trusted only in the
browser that wrote it: someone else's "Churn model" is not the one this
browser holds. `useUnavailablePipelines` moves to `services/projects` as
`useLocalPipelineStatus`, since both pages need it and it answers two
questions rather than one.

A derived name keeps what the ask was about: trimming a dangling
preposition off the end must not amputate the subject with it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@camielvs
camielvs force-pushed the 09-22-feat_projects_that_can_be_shared_and_cancelled branch from 74c9c32 to e5a678c Compare September 24, 2026 00:14
@camielvs
camielvs force-pushed the 09-23-feat_let_the_agent_name_the_project_and_session branch from 49c87b1 to 4b4380a Compare September 24, 2026 00:14
A run reaches a project's feed by carrying an annotation naming the project,
written at submit time — there is no run row to attach afterwards, and the
key cannot be added later because the endpoint that sets one takes the key as
a path segment and rejects this one for its slashes.

A run submitted from the browser is attributed already: the scope provider
puts the annotation in the submission. An agent submitting from its own
sandbox is not, and cannot be: the remote-env handshake carries only the
session id, and the workarea tools submit no runs. So the id never reaches
the agent that needs it, and the run it starts is filed under nothing.

The session's memory seed already briefs the agent before it spawns. It now
also carries the project id, the annotation to submit with, and the two
limits it would otherwise discover by being refused: one project per run, and
never this key on a saved pipeline, whose stored annotations decide its
version identity.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@camielvs camielvs changed the title feat(tangent): let the agent name the project, session and pipelines feat(tangent): brief the agent on naming, and on the project its runs belong to Sep 24, 2026

This branch has not been deployed

No deployments
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.

1 participant