diff --git a/README.md b/README.md index 6a3dd57..2a27aa1 100644 --- a/README.md +++ b/README.md @@ -293,17 +293,44 @@ Cycles (`A extends B extends A`), self-references, and missing parents die at parse with a clear pointer. Bottles remain `$HOME`-only — `extends:` preserves the trust boundary above. +### Provider base bottles + +Keep provider/runtime policy in one home-owned base bottle, then have +task bottles extend it. That keeps provider egress/auth in one place +without hiding security-relevant routes behind `agent_provider.template`. + +For example, `~/.bot-bottle/bottles/claude.md` can hold the Claude +provider selection and Anthropic API egress: + +````markdown +--- +agent_provider: + template: claude + +egress: + routes: + - host: api.anthropic.com + role: claude_code_oauth + auth: + scheme: Bearer + token_ref: BOT_BOTTLE_OAUTH_TOKEN +--- + +Common Claude provider boundary. +```` + +Task bottles can then inherit that provider boundary and add their own +env/git configuration without repeating the Claude route. + ### Example bottle (`~/.bot-bottle/bottles/gitea-dev.md`) ````markdown --- +extends: claude + env: GIT_AUTHOR_NAME: didericis -agent_provider: - template: claude # default; codex is also supported - dockerfile: "" # optional custom agent Dockerfile - git: user: name: "Eric Bauerfeld" @@ -314,33 +341,17 @@ git: Upstream: ssh://git@gitea.dideric.is:30009/didericis/bot-bottle.git IdentityFile: /Users/didericis/.ssh/id_ed25519_gitea KnownHostKey: ssh-ed25519 AAAA... - -# Egress routes are held by a per-bottle sidecar, not the agent. -# Auth token values go into the sidecar's environ, never into the -# agent. Provider-specific roles add non-secret placeholder env vars -# so the selected CLI starts while egress strips/re-injects auth. -egress: - routes: - - host: api.anthropic.com - role: claude_code_oauth - auth: - scheme: Bearer - token_ref: BOT_BOTTLE_OAUTH_TOKEN - - host: api.github.com - auth: - scheme: Bearer - token_ref: GH_PAT --- The `gitea-dev` bottle. Backs my work on personal projects: provider auth through egress and gitea.dideric.is over SSH. ```` -For a Codex-backed bottle, set `agent_provider.template: codex` and -use the `codex_auth` egress role for the OpenAI API route. The built-in -Codex template uses `Dockerfile.codex`; set `agent_provider.dockerfile` -to build the agent from a custom Dockerfile while keeping the -bot-bottle sidecars in place. +For a Codex-backed base bottle, set `agent_provider.template: codex` +and use the `codex_auth` egress role for the OpenAI API route. The +built-in Codex template uses `Dockerfile.codex`; set +`agent_provider.dockerfile` to build the agent from a custom +Dockerfile while keeping the bot-bottle sidecars in place. ### Example agent (`~/.bot-bottle/agents/gitea-helper.md`) diff --git a/docs/prds/0026-agent-provider-templates.md b/docs/prds/0026-agent-provider-templates.md index 06336f1..0c41485 100644 --- a/docs/prds/0026-agent-provider-templates.md +++ b/docs/prds/0026-agent-provider-templates.md @@ -58,6 +58,10 @@ agent_provider: dockerfile: ./Dockerfile.codex # optional ``` +- Provider templates do not implicitly add egress routes. Operators + should put provider-specific `agent_provider` and egress/auth routes + in home-owned base bottles such as `claude` or `codex`, then use + `extends` for task-specific bottles. - Provider-specific launch configuration for Claude and Codex, including command argv, auth placeholder behavior, and default image/Dockerfile selection. - Provider-aware egress role validation, including a new Codex auth role. diff --git a/examples/bottles/claude.md b/examples/bottles/claude.md new file mode 100644 index 0000000..bc7994c --- /dev/null +++ b/examples/bottles/claude.md @@ -0,0 +1,16 @@ +--- +agent_provider: + template: claude + +egress: + routes: + - host: api.anthropic.com + role: claude_code_oauth + auth: + scheme: Bearer + token_ref: BOT_BOTTLE_OAUTH_TOKEN +--- + +Common Claude provider boundary. Drop this file into +`~/.bot-bottle/bottles/claude.md`, then extend it from task-specific +bottles. diff --git a/examples/bottles/dev.md b/examples/bottles/dev.md index 0e1f8ed..8e9b8aa 100644 --- a/examples/bottles/dev.md +++ b/examples/bottles/dev.md @@ -1,38 +1,13 @@ --- +extends: claude + env: GIT_AUTHOR_NAME: Eric Diderich NODE_ENV: development - -cred_proxy: - routes: - - path: /anthropic/ - upstream: https://api.anthropic.com - auth_scheme: Bearer - token_ref: BOT_BOTTLE_OAUTH_TOKEN - role: anthropic-base-url - - path: /gh-api/ - upstream: https://api.github.com - auth_scheme: Bearer - token_ref: GH_PAT - - path: /gh-git/ - upstream: https://github.com - auth_scheme: Bearer - token_ref: GH_PAT - role: git-insteadof - - path: /gitea/dideric/ - upstream: https://gitea.dideric.is - auth_scheme: token - token_ref: GITEA_TOKEN - role: [git-insteadof, tea-login] - - path: /npm/ - upstream: https://registry.npmjs.org - auth_scheme: Bearer - token_ref: NPM_TOKEN - role: npm-registry --- The `dev` bottle — backs a generic development workflow. -Holds tokens for Anthropic, GitHub, a self-hosted Gitea, and npm. -Drop this file into `~/.bot-bottle/bottles/dev.md` and any agent -referencing `bottle: dev` will launch against this infrastructure. +Inherits the Claude provider boundary from `claude`. Drop this file +into `~/.bot-bottle/bottles/dev.md` and any agent referencing +`bottle: dev` will launch against this infrastructure.