Skip to content

feat(providers): operator-driven provider selection, switching, and memory migration - #2756

Merged
gavrielc merged 4 commits into
mainfrom
provider-selection
Jun 14, 2026
Merged

feat(providers): operator-driven provider selection, switching, and memory migration#2756
gavrielc merged 4 commits into
mainfrom
provider-selection

Conversation

@omri-maya

Copy link
Copy Markdown
Collaborator

What this does

Turns the agent provider into an explicit, operator-chosen property. Trunk ships the seams — a provider registry, a setup picker, an installer, a vault auth walkthrough, and the memory-migration skill — while the non-default provider payloads (Codex first) install from the providers branch.

Picking Claude changes nothing. Default installs are unaffected; everything here is additive.

Surface area

Setup

  • setup/providers/registry.ts (+ tests) — provider registry behind the picker
  • setup/provider-auth.ts, setup/lib/picked-provider.ts — vault auth walkthrough + the seam that carries the pick to agent creation
  • setup/add-codex.sh — channel-style installer that copies the Codex payload from the providers branch, wires the barrels, and pins the Codex CLI
  • setup/auto.ts, setup/cli-agent.ts, setup/environment.ts, setup/register.ts — picker wiring

Provider as a DB property

  • scripts/init-first-agent.ts, scripts/init-cli-agent.ts, src/modules/agent-to-agent/create-agent.ts — set container_configs.provider at creation; creation itself stays provider-agnostic
  • src/container-restart.ts, src/container-runner.ts, src/group-init.ts — restart + per-group scaffold honor the chosen provider

Switching + memory

  • .claude/skills/migrate-memory/SKILL.md — bidirectional memory carry across a provider switch
  • container/agent-runner/src/memory-templates/definition.md — read the imported-memory seed first turn
  • docs/provider-migration.md — what carries over, how to roll back

Compatibility

Additive. Existing Claude installs need no action. Provider choice is per-group (ncl groups config update --provider + restart), never install-wide, and memory is carried explicitly via /migrate-memory — never silently at runtime. Full notes in CHANGELOG.md and docs/provider-migration.md.

Testing

pnpm test (host) + container suite green. Validated end-to-end on a clean VM: setup → pick Codex → install → build → a live Codex agent answering, vault-only auth, zero credential in-container.

…emory migration

Make the agent provider a first-class, operator-chosen property instead of a
Claude-only assumption. Trunk gains the seams; the actual non-default payloads
(Codex first) install from the `providers` branch.

Setup
- A provider registry feeds a hard-wired setup picker (Claude | Codex). Picking
  a non-default provider installs its payload (setup/add-codex.sh, channel-style),
  runs a vault-only auth walkthrough (--step provider-auth), and records the pick
  on the first agent before its first spawn.
- Picking Claude changes nothing — default installs are byte-for-byte unaffected.

Provider as a DB property
- Provider lives on container_configs.provider (materialized to container.json,
  read by resolveProviderName). Creation stays provider-agnostic; the picked
  provider is applied via the picked-provider seam. The deprecated
  agent_groups.agent_provider path is not used.

Switching + memory
- Switch a live group with `ncl groups config update --provider` + restart.
- Memory never migrates at runtime — each provider keeps its own store. The
  /migrate-memory skill carries a group's memory across a switch in either
  direction (flat CLAUDE.local.md <-> memory/ scaffold). group-init seeds an
  imported-agent-memory note for non-default providers; the runner's memory
  definition reads it first turn. See docs/provider-migration.md.

No install-wide default, no runtime provider guard — switching is operator-by-
convention, consistent with the no-install-gating posture.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment on lines +25 to +33
## Imported agent memory

If `memory/memories/imported-agent-memory.md` exists, it holds this group's seed
instructions and/or memory carried over from a previous agent provider — placed
there by the operator's tooling (group creation, or the operator running
`/migrate-memory`). Read it on your first turn and treat its contents as binding:
it may define who you are and how to behave. Integrate its facts into your memory
files as you work. Files it references live in the workspace root and remain
readable; never modify files that belong to another provider's memory system.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think we can add this info as part of the migration when relevant, instead of having it always there, no?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes thats possible, looking into it

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Moved it into /migrate-memory (the step that writes the imported file + its index pointer) and dropped the always-on block from definition.md.
It now shows up only when an import actually happened. 6d521a9

omri-maya and others added 2 commits June 14, 2026 12:12
The "read imported-agent-memory.md, treat it as binding" doctrine sat in the
memory definition that every group loads, but it only matters when an import
actually happened. Move it into the /migrate-memory skill — the step that
writes the imported file and its index pointer (which the agent inlines into
its prompt each turn) — and drop the always-on block from definition.md.

Addresses review feedback on #2756.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread .claude/skills/migrate-memory/SKILL.md Outdated
@gavrielc
gavrielc merged commit a142c49 into main Jun 14, 2026
1 check passed
technicalpickles pushed a commit to technicalpickles/nanoclaw that referenced this pull request Jul 12, 2026
The "read imported-agent-memory.md, treat it as binding" doctrine sat in the
memory definition that every group loads, but it only matters when an import
actually happened. Move it into the /migrate-memory skill — the step that
writes the imported file and its index pointer (which the agent inlines into
its prompt each turn) — and drop the always-on block from definition.md.

Addresses review feedback on nanocoai#2756.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
technicalpickles pushed a commit to technicalpickles/nanoclaw that referenced this pull request Jul 12, 2026
feat(providers): operator-driven provider selection, switching, and memory migration
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