Skip to content

feat(runtime): migrate agent tools to child sessions - #1385

Merged
likun666661 merged 2 commits into
mainfrom
agent/child-session-tool-migration
Jul 23, 2026
Merged

likun666661 merged 2 commits into
mainfrom
agent/child-session-tool-migration

Conversation

@likun666661

@likun666661 likun666661 commented Jul 23, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Route fresh agent_spawn calls and new agent_swarm items through the linked child-session primitive introduced in PR feat(runtime): add child-session runtime primitive #1376.
  • Preserve the existing foreground/synchronous parent tool boundary, cancellation propagation, bounded concurrency, input ordering, and swarm all-settled behavior.
  • Add a canonical SubagentExecutionRef and mixed agent_list / agent_output read model so child sessions are addressed by childSessionId, while legacy same-session child runs remain inspectable by runId.
  • Return both childSessionId and runId for newly spawned children, persist child-session task ownership plus swarm/item lineage, and wire the dedicated capability through Desktop, CLI/TUI, and headless hosts.

Continuation and compatibility

  • resume_run_ids now resolves a returned runId to either a legacy same-session child run or a linked child Session. A fresh swarm child is continued by creating a new session-inline AgentRun in that same child Session, with durable resumedFromRunId lineage.
  • Adaptive provider-rate-limit recovery is preserved for fresh child sessions. Each retry creates another AgentRun in the same child Session, records retriedFromRunId, reuses the durable child runtime snapshot, and keeps the resulting childSessionId + runId consumable by later resume_run_ids calls.
  • agent_list.runs remains the legacy projection; agent_list.executions is the canonical mixed child-session / legacy-run view and projects the latest child-session run as currentRunId.
  • Legacy tasks.json import and recovery now preserve TaskOwner.sessionId alongside the JSONL event-ledger copy.
  • New child creation keeps the current fresh context semantics. The proposed contextMode: "fork" is intentionally not exposed yet: it needs explicit model-input snapshot semantics, artifact/checkpoint handling, and distinct fork provenance rather than pretending that fresh child creation already provides those guarantees.
  • This is PR 3 in the implementation sequence for design(runtime): model subagents as linked child sessions #1366. Broader host-level multi-turn UX remains follow-up work.

Validation

  • npm run lint
  • npm run format:check
  • npm run build
  • npm --workspace @maka/storage test
  • Focused runtime suites — 270 passed
  • Focused storage fallback regression — passed

Refs #1366

中文说明

概要

  • 将新的 agent_spawn 和 agent_swarm fresh item 切换到 PR feat(runtime): add child-session runtime primitive #1376 引入的关联 child session runtime primitive。
  • 保持父 tool call 前台同步等待、取消传播、有界并发、输入顺序和 swarm all-settled 语义不变。
  • 引入统一的 SubagentExecutionRef 与混合 agent_list / agent_output 读模型:新的 child session 使用 childSessionId 定位,旧的同 session child run 继续使用 runId 查询。
  • 新建子 agent 返回 childSessionId + runId,持久化 task owner 的 child session 引用与 swarm/item lineage,并完成 Desktop、CLI/TUI、headless host 的能力接线。

Continuation 与兼容性

  • resume_run_ids 现在会把返回的 runId 解析为 legacy same-session child run 或 linked child Session。fresh swarm child 会在同一个 child Session 内创建新的 session-inline AgentRun,并持久化 resumedFromRunId lineage。
  • fresh child session 保留自适应 RateLimit 恢复:每次 retry 都在同一个 child Session 内创建新 AgentRun,记录 retriedFromRunId,复用 durable child runtime snapshot,并让最终的 childSessionId + runId 仍可继续交给后续 resume_run_ids。
  • agent_list.runs 保留为 legacy projection;agent_list.executions 是 child session 与 legacy run 的规范混合视图,并把 child session 最新的 run 投影为 currentRunId。
  • legacy tasks.json 导入和恢复现在会保留 TaskOwner.sessionId,与 JSONL event ledger 中的元数据副本一致。
  • 新 child 只实现当前的 fresh 上下文语义。讨论中的 contextMode: "fork" 暂不暴露,因为它需要明确的模型输入快照、artifact/checkpoint 处理和独立的 fork provenance。
  • 这是 design(runtime): model subagents as linked child sessions #1366 实现序列中的 PR 3;更完整的 host 多轮交互 UX 留给后续 PR。

验证

  • npm run lint
  • npm run format:check
  • npm run build
  • Storage 全量测试
  • Runtime 相关测试:270 passed
  • Storage fallback 回归测试通过

@likun666661

Copy link
Copy Markdown
Member Author

Follow-up review on a2eaa806. The overall migration direction looks good, and the current typecheck/test/e2e checks are green. I think there are two swarm behavior regressions that should block the fresh-swarm migration, plus one smaller persistence gap:

  1. Fresh swarm results cannot be consumed by the advertised resume_run_ids path. Fresh items now run in linked child sessions and return childSessionId + runId, but every resume_run_ids entry still goes through prepareChildAgentResume(parentSessionId, runId). That lookup only accepts legacy child runs stored in the parent session and explicitly rejects session-inline runs. As a result, copying the runId returned by a new swarm item back into resume_run_ids fails with “resume source ... was not found”. Please either add a child-session execution-ref continuation path, or keep fresh agent_swarm items on the legacy path until that primitive exists. Merely documenting resume_run_ids as legacy-only would still be a regression in the public tool contract.

  2. Adaptive rate-limit recovery is disabled for every fresh child-session item. The rate-limit branch now requires !effectiveResult.childSessionId, so a fresh item that receives a transient RateLimit is settled immediately as failed: it does not retry, does not trigger capacity shrink/backoff, and the swarm returns partial. The new test explicitly locks in this behavior. The durable model should create another AgentRun inside the same child session and update its current run; if that continuation/retry primitive is intentionally deferred, I would defer the fresh-swarm migration as well. The agent_spawn migration can still land independently.

  3. The Task Ledger compatibility recovery path drops the new owner session reference. TaskOwner.sessionId is now written for durable child ownership, but normalizeOptionalOwner() in packages/storage/src/task-ledger-store.ts reconstructs only actor/agentId/runId/turnId. Normal event-ledger reads retain the field, but legacy import, tasks.json fallback, and untrusted-cache recovery lose it and can re-import the owner without its child-session identity. Please copy sessionId there and add a storage round-trip/fallback test.

The spawn identity wiring, cancellation composition, bounded concurrency, mixed list/output authorization, and backward-compatible result schemas otherwise look coherent.

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