Agents: full detail page at /agents/<slug> - #172
Merged
Conversation
Covers the page at /agents/<slug>: the identity card's editable display name beside its immutable slug, the default-model select, the full system-prompt editor, the skills section, recent runs linking into the Insights run surface, and the Duplicate/Archive/Save trio in the top bar's action slot. Every edit is asserted on the request body that leaves the page, so a second write path would fail the suite rather than pass it quietly. Also covers the archive/restore mutation this needs on the owning package: PUT /agent-definitions/:id/status writes only the row's lifecycle status, leaves the definition's asset and git history intact, refuses anything outside the schema's two states, and 404s for an unknown definition or a workbench host.
Replaces the agent placeholder with the real screen: an identity card (editable display name, immutable slug in muted mono, lifecycle state), a default-model select over the bench's catalog, a full system-prompt editor, the pinned-skills picker, and recent runs linking into the Insights run surface. Duplicate, Archive/Restore, and Save live in the StageTopBar action slot, with crumbs Agents -> display name. Every write reuses a mutation that already existed: display name and system prompt through PUT /agent-definitions/:id, the model through the guided capability route, skills through PUT .../skills, and a duplicate through the same POST /agent-definitions the create panel uses. One Save writes only the dirty parts. Archive is the one lifecycle verb that had no route, so it lands in @corbits/agent-directory as PUT /agent-definitions/:id/status: it moves the row between `deployed` and `stopped` and touches nothing else, which is what makes restoring it a single write back rather than a re-create. Delete stays out — tearing down a definition's asset and history has no route, and archiving is the reversible lifecycle the platform backs. A description field stays out too: a definition's row description IS its display name, and the purpose blurb inside its workflow.json has neither a read nor a write route today.
…ring paths Review follow-ups, as tests first: selecting "Bench default" on an agent with a pinned model is a real edit that clears it; a Save that lands partway names the parts that committed alongside the one that failed; a duplicate whose handle collides says what collided instead of "try again"; Duplicate waits while the editor is dirty rather than copying the saved version behind the person's back; and the page titles from the same derived display name the roster uses. On the package side: a definition resolves by its immutable slug through its own route (so an agent past the listing's pagination ceiling still answers on its own URL), and un-pinning a model is its own verb that leaves the prompt and tool-package pins untouched.
… detail page Review fixes for the agent detail page: - "Bench default" is a writable state again. Model dirtiness now compares against the loaded value alone, and clearing goes through a new DELETE /agent-definitions/:id/capabilities/model — its own verb, because "no model" is not a name the capability route's inventory check could accept. `withoutAgentModel` drops the inference source and leaves everything else alone. - A Save is three requests, so it can land partway. It now reports which parts committed and which did not, and reloads either way, instead of claiming a clean failure over a half-applied change. - A duplicate whose handle already exists says what collided; retrying could never have cleared it. - Duplicate waits while the editor is dirty, with a caption saying why, rather than silently copying the saved version. - Duplicating awaits the directory refresh before navigating, so the new agent's page no longer flashes "No such agent". - The slug resolves server-side through GET /agent-definitions/by-name/:name instead of scanning the definitions listing's single page, so an agent past that cap still answers on its own URL. - The page derives its display name exactly like the roster does, so one agent never reads under two names. - The archive route now documents the status invariant it relies on and every other writer of `workflow_definition.status` in this build. Polish: react-ui's Input for the display name, run states in words rather than wire enums, the archived caption says chats already running keep going, and the stale header comment about a removed roster panel is gone.
create-agent-panel no longer re-exports slugify after the search-morph rebase. Duplicate-handle minting goes through the same @corbits/slug the create panel already uses.
TheGreatAxios
force-pushed
the
cl-6414-agent-detail-page
branch
from
August 21, 2026 00:36
d51e635 to
17b8a07
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes CL-6414 — https://linear.app/abklabs/issue/CL-6414
Replaces the
/agents/<slug>placeholder with the real agent detail page.What's on the page
deriveDisplayName/withDisplayNames, PR Agents: display names with slug as stable identifier #158) in react-ui'sInput, the immutable slug beside it in muted mono, and the lifecycle state in words next to its pill.Bench defaultas a real, writable state.AgentSkillsPickerover the bench's skill registry; attach/detach is a real mutation.Running now,Failed), each linking to the existing Insights run surface.StageTopBaraction slot; crumbs are Agents → display name.Write-path decisions
PUT /agent-definitions/:idPOST /agent-definitions/:id/capabilities(kind: "model")DELETE /agent-definitions/:id/capabilities/model(new)PUT /agent-definitions/:id/skillsPUT /agent-definitions/:id/status(new)POST /agent-definitions(same call the create panel makes)GET /agent-definitions/by-name/:name(new)One Save writes only the dirty parts. Those parts are separate requests, so a Save can land partway — the page reports exactly which parts committed and which failed, and reloads either way, rather than claiming a clean failure over a half-applied change. Folding the three into one transactional route is the real fix and is deliberately deferred rather than faked here.
Review round applied
Bench defaulton a pinned agent is a real edit; clearing writes through the new DELETE verb (withoutAgentModeldrops the inference source, leaving prompt and tool-package pins untouched).SaveReportnames saved and failed parts; the notice is held by the route so it survives the reload."triage-bot-copy" already exists — open that copy, or rename it, before duplicating this agent again) instead of a "try again" a retry could never satisfy.by-name), so agent CL-6324: rebase the stack onto main, and what the first real boot found #101 answers on its own URL instead of 404ing off a truncated listing page.The
workflow_definition.statusinvariantWriters of that column in this build:
@intx/hub-sessions'ensureWorkflowDefinitionForAssetinserts with the column default (deployed) underonConflictDoNothingon(assetId, wireHash)— re-deploying the same definition body over an archived row is a no-op and cannot silently un-archive it. Editing an agent through this package's routes only repopulates the asset; it never re-projects a definition row.apps/hub'sundeployAgentDefinition, which writesstopped— the same direction as archiving, so the two cannot fight.Interchange's
workflowDefinitionStore.rollbacktouchescurrentVersion, notstatus.The one hole, stated loudly: deploying a changed body over the same asset mints a second definition row (new
wireHashmisses the unique constraint),deployedby default, beside the archived one. Nothing in this build takes that path for a hand-authored agent — onlycreateAgentDefinitionCoreand Interchange's own selector deploys call the ensure — but archiving by row status is what makes it reachable, and it is real rather than hypothetical.Scoped out / deferred
descriptionIS its display name (wherederiveDisplayNamereads it), and the purpose blurb inside itsworkflow.jsonhas neither a read nor a write route today. A "Description" input would have edited the display name twice.Only the agent entry is removed from
detail-placeholders.tsx; Skills, Plugins, and Routines placeholders stay for their own tickets.Checks
bun run checkpasses (typecheck, lint, tests) except two pre-existing failures inworkflows/assistant— tool-package pin versions and the connector-request scenario — unrelated to this branch and failing for the same reasons onmain.https://claude.ai/code/session_01Shhie5zM8L54bLHq5gFQti