Skip to content

feat(agent-core-v2): add a fork parameter to the Agent tool - #3007

Open
7Sageer wants to merge 11 commits into
mainfrom
fork-subagent
Open

feat(agent-core-v2): add a fork parameter to the Agent tool#3007
7Sageer wants to merge 11 commits into
mainfrom
fork-subagent

Conversation

@7Sageer

@7Sageer 7Sageer commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator

Related Issue

No linked issue — the problem is explained below.

Problem

The Agent tool always spawns subagents with zero context: the entire background for a task must be re-briefed into the prompt. For work that builds on the current conversation (continuing an exploration, letting a specialized profile act on what was already established), the subagent cannot see any of it, and re-briefing is both lossy and token-expensive.

What changed

Fork and spawn flow

  • The Agent tool accepts an optional fork parameter (default false, current behavior unchanged). With fork: true the subagent starts from a one-time snapshot of the calling agent's conversation history — seeded into the child's context memory as ordinary, replayable context.append_message records — then receives the task prompt prefixed with an inheritance notice framing the seeded messages as reference material, not its own experience.
  • A fork happens mid-turn, so the parent's trailing assistant message still carries the in-flight Agent tool call that can never close in the child. Instead of trimming that exchange (the v1 trimTrailingOpenToolExchange semantics this PR started with), the seed now closes it: each unanswered trailing tool call gets a synthetic result marking it as still executing with an unknown outcome. The seeded conversation stays protocol-valid, keeps the parent's final step visible as reference, and partially answered parallel batches keep their completed results.
  • The seed and the binding-snapshot overlay live in a single shared path: the tool delegates the spawn to IAgentLifecycleService.fork (extended with label passthrough), which already backs side-question (btw) agents — so the close helper also fixes btw agents forked while the main agent is mid-turn reporting the in-flight tool call's result as lost.
  • A fork inherits the caller's effective runtime (own profile, tool set, model) to preserve the provider's prompt-cache prefix: combining fork with resume, a different subagent_type, or a model override is rejected as a tool error, and the subagents allowlist is skipped since self-inheritance is not a delegation. Because the child is overlaid with the caller's live binding snapshot rather than re-resolved from the catalog, a fork works even after the caller's profile leaves the session catalog, and records forkedFrom provenance in the session metadata.
  • Follow-up: the four goal tools no longer gate registration on agent identity. They were previously contributed with a main-agent-only when, so a forked child silently lost CreateGoal/GetGoal/SetGoalBudget/UpdateGoal from its tool section — breaking the identical-tool-surface promise above and invalidating the inherited prompt-cache prefix (tools serialize ahead of messages). Registration is now profile-driven like every other tool, while subagent authority stays enforced at execution time by the goal service's existing agent check: a forked child advertises the tools (cache parity) and gets a stable goal.unsupported_agent rejection if it calls one. The convention — the registration surface must be a pure function of session-shared facts, capability differences live at execution time — is documented on AgentToolContributionOptions.when and in the package AGENTS.md.
  • The subagent spawn orchestration — profile resolution, allowlist and model validation, binding, runtime lease, permission-mode and user-tool inheritance, prompt-prefix application — is consolidated into ISessionSubagentService.planSpawn/spawn, shared by the Agent tool and AgentSwarm instead of being near-verbatim copies in three places. One visible consequence: spawn configuration errors (unknown agent type, unresolvable model) now fail upfront at plan time instead of surfacing as identical per-task failures across a swarm.
  • AgentSwarm accepts the same fork parameter: every item-spawned subagent starts from the caller's snapshot (labels keep their swarmItem), and fork combined with resume_agent_ids, subagent_type, or model is rejected. The tool description states when fork is appropriate and when independent tasks should stay zero-context.
  • The tool description now states that zero context is the default and when to pass fork: true.
  • Follow-up gating: the stale-todo reminder now binds only into the main agent — subagents (forked or not) share the session todo list but are no longer nudged to maintain a list they do not own.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

@7Hanrui

7Hanrui commented Aug 17, 2026

Copy link
Copy Markdown

@codex review

@changeset-bot

changeset-bot Bot commented Aug 17, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 65af0ca

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6916cb4847

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +340 to +344
const requestedProfileName = args.subagent_type?.length
? args.subagent_type
: fork
? (own.profileName ?? DEFAULT_PROFILE_NAME)
: DEFAULT_PROFILE_NAME;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve the caller's live binding when forking

When the caller's profile has changed after its initial bind, this reconstructs the child from the catalog profile name rather than copying profile.data(). For example, TowerInitTool enables the remaining Tower tools via addActiveTool, but a subsequent fork: true child is rebound to the base agent profile and loses those tools; prompt/profile snapshots can similarly diverge after catalog changes. Use the existing snapshot semantics in IAgentLifecycleService.fork/applyBindingSnapshot, while trimming the inherited history, so the advertised profile and tool-set inheritance is real.

Useful? React with 👍 / 👎.

const requestedProfileName = args.subagent_type?.length
? args.subagent_type
: DEFAULT_PROFILE_NAME;
const fork = args.fork === true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Match fork approvals against the caller profile

When fork: true is passed without subagent_type—the documented form—the earlier profileNameForDisplay calculation still falls back to coder, even though this branch actually launches the caller's profile (normally agent). The activity UI is therefore mislabeled, and more importantly matchesRule evaluates permission rules against coder, so an Agent(coder) rule can approve launching a different profile. Resolve the fork's display and rule subject from this.profile.data().profileName.

Useful? React with 👍 / 👎.

@7Hanrui

7Hanrui commented Aug 18, 2026

Copy link
Copy Markdown

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0c96eaa17a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +348 to +352
const requestedProfileName = args.subagent_type?.length
? args.subagent_type
: fork
? (own.profileName ?? DEFAULT_PROFILE_NAME)
: DEFAULT_PROFILE_NAME;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Allow forks after the source profile is withdrawn

When a workspace, user, or plugin profile is withdrawn after the caller has bound it, fork: true derives that profile name here but the later unconditional catalog.get(requestedProfileName) returns undefined, so the fork fails with PROFILE_UNKNOWN even though the caller still has the complete live binding snapshot. Fresh evidence after the earlier review is that the snapshot overlay was added, but the catalog lookup remains a prerequisite; create the child unbound and apply the snapshot, or otherwise avoid requiring the old catalog entry for forks.

AGENTS.md reference: packages/agent-core-v2/AGENTS.md:L5-L7

Useful? React with 👍 / 👎.

Comment on lines +372 to +373
const binding = fork
? { model: own.modelAlias, thinking: own.thinkingLevel }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Record the source agent on forked children

For every fork: true launch, this path still creates the child without passing forkedFrom, so registerAgent persists forkedFrom: undefined; session metadata consumers therefore cannot distinguish this fork from an ordinary subagent spawn. The lifecycle's existing fork() path records the source ID specifically as durable provenance, so this create call should likewise pass the caller agent ID when fork is set.

Useful? React with 👍 / 👎.

Spawning with fork: true starts the subagent from a one-time snapshot of
the calling agent's completed conversation history — same profile, tool
set, and model — instead of zero context. The seed trims the trailing
open tool exchange (the in-flight Agent call itself) before appending
into the child's context memory, and the first prompt carries an
inheritance notice framing the seeded history as reference material.

Fork rejects resume, a different subagent_type, or a model override as
tool errors, and skips the subagents allowlist since a self-inheritance
is not a delegation.
…gent

Subagents share the session todo list but no longer receive the
stale-todo nudge — the reminder injector now registers only on the main
agent, so delegated and forked agents are not prompted to maintain a
list they do not own.
…launches correctly

Review follow-ups for the Agent tool fork mode:

- overlay the caller's live profile.data() via applyBindingSnapshot after
  the catalog re-bind, so ephemeral addActiveTool deltas, the rendered
  system prompt, and runtime model/subagents updates survive the fork;
  skip the profile prompt prefix since the caller's prefixed first
  prompt is already part of the seeded history
- resolve the fork activity label and approval-rule subject from the
  caller's own profile instead of falling back to the default subagent
  type, so an Agent(<other profile>) rule cannot approve a fork
…rimming them

Fork seeding now answers the source's trailing open tool calls with a
synthetic in-flight result instead of cutting the whole trailing
exchange: the seeded history stays protocol-valid, keeps the source's
final step visible as reference, and no longer confuses side-question
(btw) agents forked while the main agent is mid-turn. The close helper
is shared by the Agent tool fork and IAgentLifecycleService.fork.

Fork launches also stop requiring the caller's profile to still exist
in the session catalog: the child is created unbound and overlaid with
the caller's live binding snapshot, matching the lifecycle fork path,
and now records forkedFrom provenance.
@7Hanrui

7Hanrui commented Aug 18, 2026

Copy link
Copy Markdown

@codex review

@pkg-pr-new

pkg-pr-new Bot commented Aug 18, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@3fa0d0a
npx https://pkg.pr.new/@moonshot-ai/kimi-code@3fa0d0a

commit: 3fa0d0a

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: d32a87107c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@7Hanrui

7Hanrui commented Aug 18, 2026

Copy link
Copy Markdown

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Swish!

Reviewed commit: 51b5403938

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

# Conflicts:
#	packages/agent-core-v2/test/agent/fullCompaction/fullCompaction.test.ts
#	packages/agent-core-v2/test/agent/loop/loop.test.ts
#	packages/agent-core-v2/test/tool/tool.test.ts
@7Hanrui

7Hanrui commented Aug 18, 2026

Copy link
Copy Markdown

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4b8095d64d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +145 to +146
created = plan.fork
? await this.agentLifecycle.fork(opts.callerAgentId, { labels: opts.labels })

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Bind the fork profile before activating child tools

When the caller uses a restrictive profile, this fork path creates the child unbound: AgentLifecycleService.create() activates tool contributions while activeToolNames and disallowedTools are unset, which registers every available tool, and the subsequent applyBindingSnapshot() does not deactivate those registrations. Consequently a fork of a read-only or otherwise restricted agent can gain tools such as Write or Bash instead of inheriting the caller's tool set. Fresh evidence beyond the earlier live-binding comment is the finalized delegation to this existing lifecycle path, whose activation ordering leaves already-registered tools intact; seed the snapshot before activation or explicitly reconcile/deactivate tools afterward.

Useful? React with 👍 / 👎.

@7Hanrui

7Hanrui commented Aug 19, 2026

Copy link
Copy Markdown

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

Reviewed commit: 65af0ca0e3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

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