feat(managed-agent): add session lifecycle operations - #6140
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
PR SummaryMedium Risk Overview The Reviewed by Cursor Bugbot for commit 30788ec. Configure here. |
Greptile SummaryThe PR expands Claude Managed Agents from a blocking run-session tool into a durable session lifecycle API.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains; the prior documentation, exact-limit truncation, fractional-limit, and non-page-aligned pagination issues are fixed in the current code.
|
| Filename | Overview |
|---|---|
| apps/sim/lib/managed-agents/session-client.ts | Adds durable session lifecycle requests, pending-tool enrichment, and full-history pagination followed by accurate newest-event capping. |
| apps/sim/tools/managed_agent/list_events.ts | Normalizes event limits, returns capped chronological events, and derives truncation from the untrimmed filtered total. |
| apps/sim/blocks/blocks/managed_agent.ts | Adds operation selection and operation-specific fields while retaining run-session defaults for existing saved blocks. |
| apps/docs/content/docs/en/integrations/managed_agent.mdx | Documents the expanded managed-agent lifecycle operations and uses the literal implemented event-limit default. |
| apps/sim/lib/managed-agents/session-client.test.ts | Covers lifecycle request shapes, pending-tool resolution, pagination boundaries, newest-event retention, totals, and invalid caps. |
| apps/sim/blocks/blocks/managed_agent.test.ts | Verifies legacy compatibility, operation routing, tool access, field visibility, and required-input behavior. |
Sequence Diagram
sequenceDiagram
participant W as Workflow
participant B as Managed Agent Block
participant C as Session Client
participant A as Anthropic Sessions API
W->>B: Create session with optional initial message
B->>C: createSession(...)
C->>A: POST /v1/sessions
A-->>W: sessionId
W->>B: Send message / inspect session
B->>C: lifecycle operation(sessionId)
C->>A: Session API request
A-->>C: status, events, or pending tool gates
C-->>W: normalized operation output
alt Tool action required
W->>B: Confirm tool or return custom result
B->>C: POST response event
C->>A: "POST /v1/sessions/{id}/events"
end
opt End lifecycle
W->>B: Interrupt, archive, or delete
B->>C: lifecycle request
C->>A: Session state transition
end
Reviews (7): Last reviewed commit: "test(managed-agent): pin the HTTP shape ..." | Re-trigger Greptile
80d79f3 to
0adfa65
Compare
|
@cursor review |
0adfa65 to
4e991d0
Compare
|
@cursor review |
|
@cursor review |
b4807ca to
1f1ec2d
Compare
|
@cursor review |
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 8ea5162. Configure here.
Adds an operation selector to the Claude Managed Agents block, backed by nine new tools alongside the existing run-session behavior: - create session (non-blocking, seeds initial_events) - send message to an existing session - get session (surfaces tool calls awaiting approval) - list events - update session (title/metadata) - interrupt session - respond to tool confirmation (allow/deny) - archive session - delete session Run Session stays the default, so blocks saved before the selector existed keep their exact behavior and field layout.
- List Events kept the OLDEST slice when capped, dropping the agent's most
recent reply. Paging is exhaustive again and the cap now keeps the newest
N after ordering, with a `truncated` flag so callers know it is a tail.
- listPaginated returned whole pages past maxItems; it now trims to the
exact cap.
- A whitespace-only title passed the update guard and would have cleared an
existing session title. Blank is now treated as not provided.
- Interrupt had no request timeout and could hang; bounded at 15s while
still honoring the workflow signal.
- Custom-tool gates were surfaced by Get Session but could not be answered,
since they need user.custom_tool_result rather than a confirmation. Adds a
Respond To Custom Tool operation and a `kind` on each pending gate so a
workflow routes to the right one.
- Docs rendered a raw ${DEFAULT_EVENT_LIMIT} placeholder for the default.
… result - `truncated` was true whenever the history size equalled the limit, even though nothing was dropped. Event reads now report the untrimmed total and the flag compares against that. - Pending-gate enrichment capped its read, which keeps the OLDEST events in page order — the opposite of where blocking gates live. It now filters to the ids being looked up as pages arrive, which is both correct regardless of page order and bounded by the id count. Paging continues on the raw page so a fully-filtered page is not mistaken for the end of the list. - Respond To Custom Tool applied one result to every id, so multiple pending tools would all receive the same output. It now answers a single call per invocation.
A limit below 1 passed the positivity check and then floored to 0, which made `slice(-0)` hand back the ENTIRE history flagged as complete — the opposite of the requested bound. The limit is now floored before it is validated, so anything that does not resolve to a positive integer falls back to the default. Also hardened the library: a zero or negative cap short-circuits to an empty result instead of falling through to `slice(-0)`, so no future caller can hit the same trap.
The id filter keeps the collected array tiny, so `maxItems` never trips and the walk continued to the end of a session's tool history even after every blocking id had been found. `listPaginated` now takes a `stopWhen` predicate and the gate lookup ends as soon as it has all the ids it came for. Also makes a blocked-but-unnamed session observable: when a session reports `requires_action` with no blocking event ids, `requiresAction` stays true — reporting false would tell a workflow the session is fine while it is parked indefinitely — and the dead end is logged and documented instead.
- A `maxItems` between 0 and 1 slipped past the zero guard and became `slice(-0)` — the whole history — because slice truncates its index toward zero. The cap is now floored at the library boundary, so no caller can hit it whatever they pass. - Update Session documented full metadata replacement but could not express a clear: an empty map normalizes to "absent". Inferring the clear from emptiness would be worse, since an untouched table is also empty and would wipe metadata on every title-only update. Adds an explicit `clearMetadata` instead, and corrects the parameter's documentation.
Method, URL, and beta header for all 11 calls, plus the SSE accept header, the separate memory-store beta (combining the two is a documented 400), and content-type only on requests that carry a body. These are the details types cannot catch and that break silently when a path is "tidied".
398229e to
30788ec
Compare
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 30788ec. Configure here.
Summary
get_sessionresolves blocking tool calls to names/inputs, so analways_askagent can be approved from a workflow instead of hanging until timeoutinitial_events, collapsing create+send into one API callBackwards compatibility
Run Session is the default operation. Blocks saved before the selector existed have no stored
operationvalue, so:managed_agent_run_sessioncontent,sessionId,inputTokens,outputTokens)blocks/blocks/managed_agent.test.tspins all of this.Wire accuracy
Every shape verified against the live Managed Agents docs, not from memory:
user.tool_confirmationusesdeny_message(notmessage) and takes the tool-use event id fromstop_reason.event_idstypes[]on the events list is a real repeatable query paraminitial_eventsaccepts onlyuser.message/user.define_outcome, validation is all-or-nothingrunningsessionagent-memory-2026-07-22beta headerType of Change
Testing
bun run lint,tsc --noEmit, and 183 unit tests pass. Not yet exercised against a live Claude workspace.Checklist