Skip to content

Research: user-configurable subagent model/provider policy #41

Description

@badcuban

Summary

Research whether Threadlines can let users choose how subagents are run separately from the main composer model. Motivating example: use Claude Fable 5 as the main model, but route cheaper/read-heavy delegated work to GPT-5.5, GPT-5.4-mini, Haiku, Sonnet, or another configured provider instance.

Short version: same-provider subagent model control looks feasible. Cross-provider subagents are possible only if Threadlines owns the child-agent orchestration instead of relying purely on Claude/Codex native subagent internals.

Why

Larger coding models increasingly use subagents for exploration, review, and parallel work. That can be useful, but it can also make expensive main-model choices multiply across delegated work. Users need predictable controls for cost, latency, and quality without disabling subagents entirely.

Research findings

Current Threadlines shape

Threadlines currently has one primary ModelSelection path for the active provider session:

  • Web composer dispatches thread.turn.start with modelSelection.
  • Server resolves modelSelection.instanceId to a configured provider instance.
  • Provider adapters map the selected model and options into the native provider runtime.

Relevant local areas:

  • packages/contracts/src/orchestration.ts: thread.turn.start and related payloads carry modelSelection, runtimeMode, and interactionMode.
  • packages/contracts/src/model.ts: model selection and provider option selection schema.
  • apps/server/src/orchestration/Layers/ProviderCommandReactor.ts: resolves provider instance, handles same-provider reuse/restart and cross-driver handoff for the main session.
  • apps/server/src/provider/Layers/CodexAdapter.ts and CodexSessionRuntime.ts: pass Codex model, effort, service tier, and collaboration settings to app-server.
  • apps/server/src/provider/Layers/ClaudeAdapter.ts: maps Claude model, effort, fast mode, thinking, permission mode, and resume state into Claude Agent SDK query options.
  • apps/web/src/components/chat/ProviderModelPicker.tsx, ModelPickerContent.tsx, and apps/web/src/modelSelection.ts: existing provider-instance-aware picker patterns.
  • apps/web/src/session-logic.ts, ThreadActivityPopover.tsx, and MessagesTimeline.tsx: existing subagent/task activity presentation.

There is no separate subagentModelSelection, subagentPolicy, or cross-provider child-agent policy today.

Codex

Current Codex docs support custom subagent/agent files with model and model_reasoning_effort. Codex can also choose cheaper/faster models automatically if these are not pinned. The app-server overview includes turn/start, model/list, collaborationMode/list, config reads/writes, and external-agent config import.

Threadlines already passes main-turn model/effort into Codex turn start and collaboration-mode settings, but those are derived from the main turn selection, not a separate subagent preference.

Docs:

Claude

Current Claude Code docs support custom subagents with frontmatter fields including model/effort, built-in subagent behavior, explicit @ subagent invocation, an Agent tool model parameter, and environment/config overrides such as CLAUDE_CODE_SUBAGENT_MODEL.

The installed local @anthropic-ai/claude-agent-sdk types expose programmatic agents?: Record<string, AgentDefinition>, where AgentDefinition supports model?: string and effort?: .... The Task/Agent tool input also has a model override for Claude model families. Threadlines currently does not pass custom agents definitions into Claude queryOptions.

Docs:

Feasibility split

1. Same-provider subagent defaults: feasible

For Claude main sessions, Threadlines can likely generate or pass custom Claude agent definitions with chosen model/effort. For Codex main sessions, Threadlines can likely generate/configure Codex custom agents or route policy into app-server-supported collaboration/agent configuration paths.

This would allow cases like:

  • Fable 5 main, Haiku/Sonnet custom Claude subagent for read-heavy exploration.
  • GPT-5.5 main, GPT-5.4-mini Codex subagent for scans.
  • Main model inherits by default, with user-set policy caps.

2. Cross-provider subagents: feasible only with Threadlines-owned orchestration

Do not assume Claude can natively spawn a GPT subagent, or Codex can natively spawn a Claude subagent. Native provider subagents live inside their provider runtime.

The robust version is to expose a Threadlines-owned child-agent tool or MCP-style capability to the parent provider. When the parent asks for delegated work, Threadlines starts a child provider session using the selected provider/model, waits or streams progress, and returns a compact result to the parent.

This is more work, but it is the path that can make Claude Fable 5 main + GPT-5.5 subagent real and enforceable.

Proposed product model

Add a subagentPolicy concept adjacent to modelSelection, not hidden only inside the current provider picker.

Suggested presets:

  • Auto: provider/runtime chooses within sensible caps.
  • Economy: prefer cheaper/faster models for exploration and review.
  • Balanced: default model class for most subagents, higher model for correctness-sensitive roles.
  • Power: allow main-model-equivalent subagents.
  • Custom: choose by role.

Possible custom role mapping:

  • Explore: provider/model/reasoning, read-only by default.
  • Review: provider/model/reasoning, read-only by default, high reasoning cap.
  • Implement: provider/model/reasoning, write-capable only when explicitly allowed.
  • Fallback: what to do when selected subagent model/provider is unavailable.

Default UX should keep reasoning simple: let the main model choose within caps. Advanced users can pin reasoning levels per role.

Implementation sketch

Phase 1: data model and UI only

  • Add contract shape for SubagentPolicy / SubagentModelSelection near model selection contracts.
  • Add per-thread and/or sticky settings storage.
  • Extend composer controls with a compact subagent policy selector.
  • Show policy in activity metadata when subagents run.
  • No behavior change unless provider supports it.

Phase 2: same-provider native support

Claude:

  • Generate agents definitions in ClaudeAdapter query options from subagentPolicy.
  • Consider whether to use SDK agents, on-disk .claude/agents, or env/settings depending on lifecycle and resume behavior.
  • Preserve user/project subagents; avoid clobbering existing names.

Codex:

  • Investigate whether to write scoped custom agent files/config, use app-server config APIs, or pass supported collaboration settings.
  • Keep custom agent names deterministic and Threadlines-scoped.

Phase 3: Threadlines-owned cross-provider child agents

  • Add server-side child-agent orchestration capability.
  • Parent provider receives a tool/MCP capability like threadlines_spawn_subagent.
  • Tool input includes task, role, isolation mode, allowed tools, desired provider/model policy, timeout, and output format.
  • Server starts a child provider session through existing ProviderService and returns/streams compact results.
  • UI renders child runs using existing subagent/task activity primitives.

Limitations / risks

  • Prompting alone is not enforcement. Native provider runtimes may still use their own subagent model unless Threadlines configures or replaces that path.
  • Cross-provider child agents will not naturally share provider prompt cache or native resume state.
  • Editing subagents can conflict on a shared checkout. MVP should favor read-only/review subagents, then add explicit checkout isolation or serialized write policy.
  • Provider accounting must remain per provider/account. A Claude parent spawning GPT child work should show both costs/usages clearly.
  • Model availability and version gates matter. UI should disable unsupported choices with reasons, like runtime mode currently does.
  • Existing provider-native subagent activity may not report exact model/reasoning today; telemetry may need extension.
  • User/project-defined subagents must not be silently overwritten.

Open questions

  • Should this be a thread-level policy, project default, global user default, or all three with precedence?
  • Should the initial MVP support only read-only subagents?
  • Should Threadlines disable native provider subagents when cross-provider policy is enabled, or let both coexist?
  • What isolation should write-capable cross-provider subagents use: shared checkout, per-child worktree, or serialized patch application?
  • What should happen if the selected subagent provider is unavailable mid-turn?
  • How should subagent budget caps be expressed: tokens, dollars, model tier, max concurrency, or max wall time?

Acceptance criteria for future deep dive

  • Document exact provider-supported hooks for Claude and Codex in the current installed versions.
  • Prototype same-provider policy for one provider without breaking existing user-defined subagents.
  • Decide whether cross-provider support is implemented as MCP, native provider tool, or internal orchestration command.
  • Define telemetry for parent provider, child provider, selected model, actual model, reasoning/effort, duration, token usage, and failure mode.
  • Validate with at least one read-only exploration task and one review task.
  • Keep vp fmt, vp lint, and vp run typecheck passing before merging any implementation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementRequested improvement or new capability.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions