Skip to content

Design: Subagent permission surfaces and implementation agents #52

Closed

Description

@Astro-Han

Context

#49 / #51 added the first foreground read-only subagent foundation: a parent agent can spawn a child run, the child has its own runtime ledger, and the parent can inspect results through agent projection tools.

That is a useful spine, but the next step should be shaped before another implementation PR. Subagents are not one capability. They likely need several permission profiles and product modes.

Why this issue

We need one focused place to discuss the subagent surface before continuing:

  • read-only local exploration
  • web research subagents
  • implementation subagents that can edit in an isolated boundary
  • how agent_* tools are exposed to the parent model
  • when a child can prompt, block, or continue without UI approval

The design filter stays the same: simple enough, elegant enough, reassuring enough.

Immediate candidates, not yet final decisions

Two cleanup ideas came out of the first read-only pass:

  1. Put agent_spawn, agent_list, and agent_output behind a deferred agent tool group.

    • This is prompt/surface economy, not a permission boundary.
    • It may reduce accidental spawning and keep the always-on tool surface smaller.
  2. Revisit whether read-only child agents should have raw Bash.

    • Current child toolset includes Bash, Read, Glob, Grep.
    • Current policy blocks shell_unsafe in explore, but allows shell_safe through a command classifier.
    • Without OS/worktree sandboxing, classifier-based shell safety may not be reassuring enough for a feature labeled read-only.
    • Possible outcomes: remove Bash; keep only Read/Glob/Grep; introduce structured read tools; or keep Bash only after a stronger sandbox exists.

These are likely small PR-sized improvements, but they should not be treated as the whole subagent roadmap.

Open questions

1. Read-only local agents

What is the minimum useful local read-only toolset?

Options to discuss:

  • Read / Glob / Grep only
  • add structured read helpers such as git_status, git_diff, list_dir
  • keep safe Bash with tighter classification
  • keep Bash only when a real OS/worktree sandbox enforces read-only

Key invariant to preserve: a read-only child should not park on a permission prompt that no UI can answer.

2. Web research agents

Some research tasks need many subagents doing web search in parallel. That is different from local read-only exploration.

Questions:

  • Should web research be a separate subagent profile from local read-only?
  • Is web_read allowed by default for a web-research child, or does the parent/user approve the profile once?
  • How do we prevent web research children from gaining local write/shell/network-send capability?
  • What should the parent see: only summaries, citations, full traces, or all tool events?

3. Implementation agents

Implementation subagents are a separate capability, not just read-only agents with more tools.

Likely shape to discuss:

  • run in isolated worktree or sandbox
  • allow edits only inside that boundary
  • return diff, changed files, artifacts, tests, and summary
  • parent/user decides whether to apply changes
  • no silent mutation of the parent checkout

Questions:

  • Does implementation child need ask mode, execute mode, or a dedicated profile?
  • How are approvals routed if the child needs a risky tool?
  • What is the rollback/apply contract?
  • Should nested subagents wait until implementation v1 is stable?

4. Parent-facing agent tools

Current parent-facing tools are:

  • agent_spawn
  • agent_list
  • agent_output

Questions:

  • Should they move into a deferred agent group?
  • Should agent_spawn eventually accept a profile such as local_read, web_research, or implementation?
  • Should agent_list and agent_output stay always-on because they are read-only projections, or move with agent_spawn for conceptual grouping?

Non-goals for the next PR

  • Do not build the full implementation agent until its boundary is shaped.
  • Do not introduce nested subagents by default.
  • Do not treat deferred tools as a security boundary.
  • Do not rely on prompt text alone for read-only guarantees.

Possible next split

After discussion, this may split into separate PRs:

  1. Read-only subagent surface cleanup: deferred agent group plus local read-only child toolset hardening.
  2. Web research subagent profile: explicit network-read-only child mode with citation/trace expectations.
  3. Implementation subagent v1: isolated patch-producing worker with apply/review gate.

The exact split should follow from the permission model, not the other way around.

Activity

  1. Astro-Han commented on Jun 18, 2026

    @Astro-Han
    ContributorAuthor

    Current working decision

    We are not waiting on external review for this issue. Treat this as Maka's internal design workbench for the next subagent slices.

    Based on current evidence from Codex, Claude Code, and Google ADK, the clean shape is profile-based subagents, not one generic subagent with a growing permission switch.

    1. Profiles

    Maka should model subagents as a small set of explicit profiles:

    • local_read: local repository exploration. No writes, no network, no raw shell. Default first subagent profile.
    • web_research: network-read research. Many children may run in parallel, but the capability is explicit and separate from local filesystem exploration.
    • implementation: isolated worker that can edit only inside a worktree/sandbox boundary and returns diff/artifacts/tests for parent/user review.

    This keeps permission semantics readable. A child is not "a subagent with some tools"; it is a subagent running under a named product contract.

    2. Local read-only boundary

    For local_read, the most reassuring Day 1 boundary is structural:

    • allow Read, Glob, Grep
    • do not expose raw Bash
    • do not expose Write, Edit, browser, WebSearch, network-send, or nested agent spawning
    • preserve the invariant that child tools resolve to allow/block only, not prompt, because there is no child approval UI yet

    If local shell-like inspection is needed later, prefer structured read tools such as git_status, git_diff, or list_dir over arbitrary shell strings. Raw Bash should wait for a real OS/worktree sandbox or an equivalent containment layer.

    Risk framing: keeping classifier-based safe Bash is not an emergency P0 because it mostly overlaps parent explore capability, but it is a P1 contract mismatch for a feature labeled read-only.

    3. Web research boundary

    web_research should not be folded into local_read.

    It should be an explicit profile with:

    • web-read/search tools allowed
    • no local write tools
    • no raw local shell by default
    • budget/concurrency caps
    • required source/citation output in the result summary
    • full trace available through agent_output

    This supports the real use case of many research subagents without making every read-only local child network-capable.

    4. Implementation boundary

    implementation is a separate capability, not a relaxation of local_read.

    The implementation child should:

    • run in an isolated worktree or sandbox
    • allow edits only inside that boundary
    • produce diff, changed files, artifacts, tests, and summary
    • require parent/user review before applying to the parent checkout
    • keep risky approvals explicit rather than silently inheriting broad parent authority

    Nested subagents should wait until this contract is stable.

    5. Parent-facing tool surface

    agent_spawn, agent_list, and agent_output should likely move into a deferred agent group. This is prompt/surface economy, not security.

    When agent_spawn grows, it should accept an explicit profile rather than overloading instructions text:

    • profile: local_read
    • profile: web_research
    • profile: implementation

    Research basis

    • Codex subagents expose built-in roles such as explorer/worker and allow custom agent sandbox overrides; subagents inherit sandbox/approval controls, and read-only is backed by sandbox behavior.
    • Claude Code subagents have explicit tool allowlists, permission modes, hooks, MCP scoping, and worktree isolation. Its built-in Explore/Plan agents are read-only, while general-purpose can modify.
    • Google ADK distinguishes agent-as-tool from sub-agent orchestration and encourages explicit toolsets/workflows rather than one monolithic agent.

    Likely next PRs

    1. local_read cleanup: child no raw Bash; parent agent_* deferred group.
    2. web_research profile: explicit network-read child mode with citations, caps, and trace.
    3. implementation profile: isolated patch-producing worker.

    Do not start #3 until #1/#2 have made the profile model explicit enough.

  2. Astro-Han commented on Jun 18, 2026

    @Astro-Han
    ContributorAuthor

    Expanded research pass: Google ADK, OpenCode, OpenHands, LangChain, and local notes

    The earlier comment was directionally right but too narrow. I reread the local research notes under notes/local/ plus the reference-app deep dives, then checked Google ADK, OpenCode, OpenHands, and LangChain docs.

    Sources checked

    Local notes:

    • notes/local/2026-06-18-maka-subagent-design-research.md
    • notes/local/2026-06-16-agent-harness-landscape.md
    • notes/reference-deep-dive-yuejing-round-2/07-subagent-orchestration.md
    • notes/reference-deep-dive-yuejing-round-5/02-sprint-harness.md

    External docs:

    • Google ADK workflows / custom agent orchestration / callbacks
    • OpenCode agents and permissions
    • OpenHands SDK sub-agent delegation
    • LangChain multi-agent patterns
    • Existing Codex / Claude Code docs from the previous pass

    What changed after the wider pass

    The profile idea still holds, but the next design should not be framed only as local_read / web_research / implementation.

    There are four orthogonal axes:

    1. Invocation pattern

      • agent-as-tool: parent stays owner and receives result
      • handoff: another agent becomes owner
      • workflow/harness: deterministic multi-step controller calls agents
    2. Capability profile

      • local_read
      • web_research
      • implementation
      • later: evaluator/verifier, app-guide, sprint harness roles
    3. Execution/isolation profile

      • foreground blocking call
      • background/resumable call
      • same workspace
      • isolated worktree/sandbox
    4. Write-back mode

      • summary
      • decision
      • artifact
      • patch/diff

    The cleanest Maka design is to keep Day 1 as foreground agent-as-tool, but make the data model leave room for profile + writeBack + isolation instead of hardcoding a single read-only child shape.

    Lessons from Google ADK

    Google ADK is useful because it separates primitives cleanly:

    • collaborative workflows: coordinator with sub-agents
    • template workflows: sequential / loop / parallel
    • custom workflows: explicit orchestration logic
    • callbacks: lifecycle interception and control
    • AgentTool: an agent used as a tool by another agent

    The lesson for Maka is not to copy ADK state sharing directly. ADK's shared InvocationContext/session.state is elegant for app workflows but risky for coding agents if adopted blindly. Maka should keep child context isolated by default and pass state/artifacts explicitly.

    Lessons from reference app local notes

    Reference app's Task tool has more dimensions than our first PR:

    • raw subagent_type vs managed agent_id
    • built-in specialist roster
    • foreground + background
    • resume-by-id
    • TaskOutput
    • sprint harness mode
    • structured handoff packet: goal / deliverable / constraints / writeBack

    Most important transfer: writeBack mode. Implementation subagents should not simply "edit". They should declare whether the result is summary, decision, artifact, or patch.

    The sprint harness notes add another strong lesson: evaluator should be a separate role from generator. For implementation work, a future verifier/evaluator subagent should not trust the generator's claims.

    Lessons from OpenCode

    OpenCode already separates:

    • primary agents vs subagents
    • built-in General, Explore, Scout
    • Explore: read-only codebase exploration
    • Scout: external docs/dependency research
    • General: full tool access for complex tasks
    • per-agent permission config
    • task permission rules controlling which subagents a primary agent can invoke

    This is strong evidence for separating Maka's local_read and web_research instead of treating both as one generic read-only agent.

    Lessons from OpenHands

    OpenHands delegation is explicitly about parallel child agents:

    • spawn named children
    • delegate tasks to specific IDs
    • children have independent conversation context
    • results are consolidated by parent
    • max_children exists as a control knob
    • children operate in the same workspace by default

    The useful lesson is the spawn/delegate split for parallel research. The risky part for Maka is same-workspace execution if children can write.

    Lessons from LangChain multi-agent docs

    LangChain frames subagents as one pattern among several:

    • subagents: parent coordinates children as tools
    • handoffs: ownership transfers
    • skills: single agent loads context on demand
    • router: explicit dispatch step
    • custom workflow: deterministic graph/controller

    It also says subagents are best for parallel execution and large-context domains, but worse for repeat/simple tasks. That argues against making every helper a subagent. Skills/deferred tools still matter.

    Revised working shape for Maka

    Do not model subagent as one growing tool with many booleans.

    Model it as:

    agent_spawn({
      profile: 'local_read' | 'web_research' | 'implementation',
      objective: string,
      instructions?: string,
      writeBack: 'summary' | 'decision' | 'artifact' | 'patch',
      isolation?: 'same_workspace' | 'worktree' | 'sandbox',
    })

    This is conceptual, not a proposed exact API yet.

    Near-term decisions

    1. local_read

      • foreground agent-as-tool
      • isolated context
      • no raw Bash by default
      • no network by default
      • output: summary + evidence refs
    2. web_research

      • separate profile
      • network-read/search tools allowed
      • no local write/shell
      • output requires citations/source refs
      • concurrency/budget caps are first-class
    3. implementation

      • separate profile
      • isolated worktree/sandbox required
      • output is patch/artifact/tests, not silent parent mutation
      • verifier/evaluator should be a later separate profile or workflow role
    4. agent_* tool exposure

      • deferred agent group is still likely right
      • but do not treat it as security
      • profile catalog must be visible enough that the parent knows when to load it

    Updated likely PR split

    1. PR A: local-read cleanup

      • move agent_* into deferred agent group
      • remove raw Bash from local_read child toolset or otherwise make the no-shell boundary explicit
      • no profile API yet unless needed to avoid hardcoding
    2. PR B: profile-shaped spawn

      • introduce explicit profile field and internal profile registry
      • start with local_read
      • keep current runtime spine
    3. PR C: web-research profile

      • add network-read child profile with source/citation requirements
      • add budget/concurrency caps and trace expectations
    4. PR D: implementation profile design/first slice

      • only after isolation/apply/writeBack contract is clear
      • likely worktree + patch writeBack first

    Updated non-goals

    • Do not build handoff yet.
    • Do not build sprint harness yet.
    • Do not let implementation profile mutate parent workspace directly.
    • Do not conflate web research with local read-only.
    • Do not treat subagents as the answer for simple repeat tasks where skills/deferred tools are cheaper.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions