PRD 0026: Agent Provider Templates #91

Merged
didericis merged 19 commits from prd-0026-agent-provider-templates into main 2026-05-28 20:04:41 -04:00
Collaborator

closes #90

Tracking PR for PRD 0026. Implementation will follow on this branch.

closes https://gitea.dideric.is/didericis/bot-bottle/issues/90 Tracking PR for [PRD 0026](docs/prds/0026-agent-provider-templates.md). Implementation will follow on this branch.
didericis-codex added 1 commit 2026-05-28 02:07:23 -04:00
docs(prd): scaffold PRD 0026 — Agent Provider Templates
test / unit (pull_request) Successful in 27s
test / integration (pull_request) Successful in 45s
e03d90962d
Assisted-by: Codex
didericis added 1 commit 2026-05-28 02:19:41 -04:00
feat(agent): add provider templates
test / unit (pull_request) Successful in 28s
test / integration (pull_request) Successful in 40s
500fd910c4
Assisted-by: Codex
didericis added 1 commit 2026-05-28 02:36:10 -04:00
docs: add project status positioning
test / unit (pull_request) Successful in 27s
test / integration (pull_request) Successful in 40s
c9291f97e6
didericis reviewed 2026-05-28 17:19:13 -04:00
README.md Outdated
@@ -40,0 +48,4 @@
remediation flows, and unit/integration tests covering exfiltration and
sandbox escape scenarios.
Current status: personal/small-team security tool, not yet enterprise
Owner

remove this paragraph

remove this paragraph
didericis marked this conversation as resolved
didericis reviewed 2026-05-28 17:20:05 -04:00
README.md Outdated
@@ -131,2 +145,2 @@
env vars, and `~/.gitconfig` (the latter for the git-gate's
`insteadOf` rules when `bottle.git` is set).
- **agent image** — built from the provider template Dockerfile
(`Dockerfile` for Claude, `Dockerfile.codex` for Codex, or
Owner

Call the dockerfile for claude "Dockerfile.claude"

Call the dockerfile for claude "Dockerfile.claude"
didericis marked this conversation as resolved
didericis reviewed 2026-05-28 17:24:19 -04:00
README.md Outdated
@@ -288,2 +306,4 @@
GIT_AUTHOR_NAME: didericis
agent_provider:
template: claude # default; codex is also supported
Owner

It should be easy to declare a new claude agent/that shouldn't require needing to specify all the egress routes, but I want the configuration to be in one place. A bit torn how to do that...

I think it probably makes sense to have a top level "claude" bottle we extend from which sets both the "agent_provider" and the "egress" routes. OR we could have the egress routes be added via this template cue here, but that smells like a bad side design to me. Thoughts?

It should be easy to declare a new claude agent/that shouldn't require needing to specify all the egress routes, but I want the configuration to be in one place. A bit torn how to do that... I think it probably makes sense to have a top level "claude" bottle we extend from which sets both the "agent_provider" and the "egress" routes. OR we could have the egress routes be added via this template cue here, but that smells like a bad side design to me. Thoughts?
didericis marked this conversation as resolved
didericis added 1 commit 2026-05-28 17:24:53 -04:00
fix(agent): address provider review feedback
test / unit (pull_request) Successful in 35s
test / integration (pull_request) Successful in 47s
8875d8cc17
Assisted-by: Codex
Author
Collaborator

Addressed both review comments in 8875d8c: removed the requested README status paragraph and renamed the Claude agent Dockerfile to Dockerfile.claude, including the default provider/runtime references.

Addressed both review comments in `8875d8c`: removed the requested README status paragraph and renamed the Claude agent Dockerfile to `Dockerfile.claude`, including the default provider/runtime references.
didericis reviewed 2026-05-28 17:27:31 -04:00
@@ -0,0 +37,4 @@
PROVIDER_CLAUDE: AgentProviderRuntime(
template=PROVIDER_CLAUDE,
command="claude",
image="claude-bottle:latest",
Owner

Image should be changed to "bot-bottle-claude:latest"

Actually we should rename the entire project from "claude-bottle" to "bot-bottle". Try to do that in a single commit. Will follow up with gitea project renames after.

Image should be changed to "bot-bottle-claude:latest" Actually we should rename the entire project from "claude-bottle" to "bot-bottle". Try to do that in a single commit. Will follow up with gitea project renames after.
didericis marked this conversation as resolved
didericis reviewed 2026-05-28 17:29:38 -04:00
@@ -26,3 +24,4 @@
self.name = container
self._teardown = teardown
self._prompt_path = prompt_path_in_container
self._agent_command = agent_command
Owner

why is this added twice? Once as self._agent_command, another time as self.agent_command?

why is this added twice? Once as `self._agent_command`, another time as `self.agent_command`?
didericis marked this conversation as resolved
didericis reviewed 2026-05-28 17:32:18 -04:00
@@ -86,2 +93,4 @@
"codex" if agent_command == "codex" else "claude"
)
def claude_argv(
Owner

Am assuming this is agent agnostic now/should be renamed agent_argv, correct?

Am assuming this is agent agnostic now/should be renamed `agent_argv`, correct?
didericis marked this conversation as resolved
didericis reviewed 2026-05-28 17:32:49 -04:00
@@ -96,3 +104,1 @@
if self._prompt_path:
claude_tail += ["--append-system-prompt-file", self._prompt_path]
claude_tail += argv
claude_tail = [self._agent_command]
Owner

this claude specific naming in the function body should be fixed)

this claude specific naming in the function body should be fixed)
didericis marked this conversation as resolved
didericis reviewed 2026-05-28 17:35:05 -04:00
@@ -24,1 +19,4 @@
prompt_path_in_container: str | None,
*,
agent_command: str = "claude",
agent_prompt_mode: str = "claude_append_file",
Owner

It seems like there are two different prompt modes: codex_read_prompt_file and claude_append_file. Could they be shortened to just read_prompt_file and append_file? What makes them provider specific?

Also would be nice to add type hints to available options here.

It seems like there are two different prompt modes: `codex_read_prompt_file` and `claude_append_file`. Could they be shortened to just `read_prompt_file` and `append_file`? What makes them provider specific? Also would be nice to add type hints to available options here.
didericis marked this conversation as resolved
didericis reviewed 2026-05-28 17:39:01 -04:00
@@ -705,2 +706,3 @@
try:
capture_session_state(identity, exit_code=0)
if getattr(bottle, "agent_provider_template", "claude") == "claude":
capture_session_state(identity, exit_code=0)
Owner

Change capture_session_state to capture_claude_session_state, and add a comment stating the session state is agent specific (FIXME: would be better if we just froze all the data in the container and made this agent agnostic, should be a spike on how to do that/make a new issue)

Change `capture_session_state` to `capture_claude_session_state`, and add a comment stating the session state is agent specific (FIXME: would be better if we just froze all the data in the container and made this agent agnostic, should be a spike on how to do that/make a new issue)
didericis marked this conversation as resolved
didericis reviewed 2026-05-28 17:41:27 -04:00
@@ -430,2 +479,3 @@
@classmethod
def from_dict(cls, bottle_name: str, raw: object) -> "EgressConfig":
def from_dict(
cls, bottle_name: str, raw: object, *, provider_template: str = "claude",
Owner

think we want to be more specific about what "provider_template" is throughout the code: rename variables like this to agent_provider_template

think we want to be more specific about what "provider_template" is throughout the code: rename variables like this to `agent_provider_template`
didericis marked this conversation as resolved
didericis reviewed 2026-05-28 17:43:41 -04:00
@@ -0,0 +54,4 @@
```yaml
agent_provider:
template: codex # or claude
Owner

debating whether or not we should call this "type" instead of template...

debating whether or not we should call this "type" instead of template...
didericis marked this conversation as resolved
Author
Collaborator

Re #701: I agree the template cue should not implicitly add egress routes. That would hide a security boundary behind provider selection. My preference is a home-owned base bottle like claude that declares both agent_provider and Claude egress, with concrete bottles using extends: claude and adding task-specific env/git/routes. I will update the README/PRD examples around that pattern.

Re #701: I agree the template cue should not implicitly add egress routes. That would hide a security boundary behind provider selection. My preference is a home-owned base bottle like `claude` that declares both `agent_provider` and Claude egress, with concrete bottles using `extends: claude` and adding task-specific env/git/routes. I will update the README/PRD examples around that pattern.
Author
Collaborator

Re #705: Agreed. I will do the project rename as its own single commit and include the image rename to bot-bottle-claude:latest. I will also sweep docs, package/module names, env var names, state paths, labels, and image names so the rename is coherent rather than just cosmetic.

Re #705: Agreed. I will do the project rename as its own single commit and include the image rename to `bot-bottle-claude:latest`. I will also sweep docs, package/module names, env var names, state paths, labels, and image names so the rename is coherent rather than just cosmetic.
Author
Collaborator

Re #709: Correct. That surface is agent-agnostic now. I will rename it to agent_argv and follow through with exec_agent/call-site/test renames, keeping temporary compatibility aliases only if the blast radius makes that safer for this PR.

Re #709: Correct. That surface is agent-agnostic now. I will rename it to `agent_argv` and follow through with `exec_agent`/call-site/test renames, keeping temporary compatibility aliases only if the blast radius makes that safer for this PR.
Author
Collaborator

Re #707: The duplicate was a compatibility shortcut: _agent_command for the handle internals, agent_command for dashboard/tmux code that introspects the running handle. I agree it is unnecessary. I will collapse this to one public agent_command attribute and use it internally too.

Re #707: The duplicate was a compatibility shortcut: `_agent_command` for the handle internals, `agent_command` for dashboard/tmux code that introspects the running handle. I agree it is unnecessary. I will collapse this to one public `agent_command` attribute and use it internally too.
Author
Collaborator

Re #711: Agreed. I will rename the local variables and docstrings in that path from claude_* to agent_*, while leaving only explicitly Claude-only state/transcript pieces named Claude.

Re #711: Agreed. I will rename the local variables and docstrings in that path from `claude_*` to `agent_*`, while leaving only explicitly Claude-only state/transcript pieces named Claude.
Author
Collaborator

Re #717: Agreed. I will rename provider_template variables/parameters to agent_provider_template throughout so the code matches the manifest shape and avoids the vague provider/template split.

Re #717: Agreed. I will rename `provider_template` variables/parameters to `agent_provider_template` throughout so the code matches the manifest shape and avoids the vague provider/template split.
Author
Collaborator

Re #715: Agreed. I will rename this to capture_claude_session_state and add the FIXME/comment that the current transcript/session capture is agent-specific; longer term we should spike freezing provider-neutral container state instead.

Re #715: Agreed. I will rename this to `capture_claude_session_state` and add the FIXME/comment that the current transcript/session capture is agent-specific; longer term we should spike freezing provider-neutral container state instead.
Author
Collaborator

Re #713: Yes, those modes are behavior-specific rather than provider-specific. I will rename them to append_file and read_prompt_file, and add explicit type hints for the accepted prompt modes so the runtime table is tighter.

Re #713: Yes, those modes are behavior-specific rather than provider-specific. I will rename them to `append_file` and `read_prompt_file`, and add explicit type hints for the accepted prompt modes so the runtime table is tighter.
Author
Collaborator

Re #719: My recommendation is to keep template. In this design claude/codex selects a bundled runtime template: command, image, Dockerfile, prompt behavior, and auth placeholder. type reads broader and could imply a stable taxonomy rather than a concrete launch template. I can change it if you prefer, but I would keep template unless we want to rename the whole concept.

Re #719: My recommendation is to keep `template`. In this design `claude`/`codex` selects a bundled runtime template: command, image, Dockerfile, prompt behavior, and auth placeholder. `type` reads broader and could imply a stable taxonomy rather than a concrete launch template. I can change it if you prefer, but I would keep `template` unless we want to rename the whole concept.
Author
Collaborator

Plan of attack after review feedback:

  1. Keep agent_provider.template as the manifest key. No rename to type.
  2. Update docs/examples to recommend home-owned base bottles like claude/codex that define both agent_provider and provider egress/auth routes; task-specific bottles should use extends.
  3. Do a full project rename in a dedicated commit: claude-bottle -> bot-bottle, including docs, CLI strings, image/container/network labels, state/cache paths, env vars, and the Python package/module rename from claude_bottle to bot_bottle. No legacy env/state compatibility aliases needed.
  4. Rename default images to provider-specific bot-bottle names, starting with bot-bottle-claude:latest and matching Codex naming.
  5. Clean up agent-agnostic runtime naming: claude_argv -> agent_argv, exec_claude -> exec_agent, local claude_* variables -> agent_*, and update tests/call sites.
  6. Collapse duplicate command storage to a single agent_command attribute.
  7. Rename prompt modes to behavior names (append_file, read_prompt_file) and add explicit type hints for allowed prompt modes.
  8. Rename capture_session_state to capture_claude_session_state and add a FIXME noting current transcript/session capture is agent-specific; provider-neutral container-state freezing should be a follow-up spike.
  9. Rename vague provider_template variables/params to agent_provider_template throughout.

I will wait for approval before making these code changes.

Plan of attack after review feedback: 1. Keep `agent_provider.template` as the manifest key. No rename to `type`. 2. Update docs/examples to recommend home-owned base bottles like `claude`/`codex` that define both `agent_provider` and provider egress/auth routes; task-specific bottles should use `extends`. 3. Do a full project rename in a dedicated commit: `claude-bottle` -> `bot-bottle`, including docs, CLI strings, image/container/network labels, state/cache paths, env vars, and the Python package/module rename from `claude_bottle` to `bot_bottle`. No legacy env/state compatibility aliases needed. 4. Rename default images to provider-specific bot-bottle names, starting with `bot-bottle-claude:latest` and matching Codex naming. 5. Clean up agent-agnostic runtime naming: `claude_argv` -> `agent_argv`, `exec_claude` -> `exec_agent`, local `claude_*` variables -> `agent_*`, and update tests/call sites. 6. Collapse duplicate command storage to a single `agent_command` attribute. 7. Rename prompt modes to behavior names (`append_file`, `read_prompt_file`) and add explicit type hints for allowed prompt modes. 8. Rename `capture_session_state` to `capture_claude_session_state` and add a FIXME noting current transcript/session capture is agent-specific; provider-neutral container-state freezing should be a follow-up spike. 9. Rename vague `provider_template` variables/params to `agent_provider_template` throughout. I will wait for approval before making these code changes.
didericis added 3 commits 2026-05-28 18:01:19 -04:00
Assisted-by: Codex
Assisted-by: Codex
docs(agent): document provider base bottles
test / unit (pull_request) Successful in 34s
test / integration (pull_request) Successful in 53s
cacba087c9
Assisted-by: Codex
didericis reviewed 2026-05-28 18:11:20 -04:00
README.md Outdated
@@ -421,3 +426,3 @@
"upstream": "https://api.anthropic.com",
"auth_scheme": "Bearer",
"token_ref": "CLAUDE_BOTTLE_OAUTH_TOKEN",
"token_ref": "BOT_BOTTLE_OAUTH_TOKEN",
Owner

This env var should be BOT_BOTTLE_CLAUDE_OAUTH_TOKEN. Update accordingly.

Also note that this is specific to an example when we're using a claude agent provider in the docs.

This env var should be BOT_BOTTLE_CLAUDE_OAUTH_TOKEN. Update accordingly. Also note that this is specific to an example when we're using a claude agent provider in the docs.
Author
Collaborator

Re #732: Agreed. I will update the Claude-provider examples/docs to use BOT_BOTTLE_CLAUDE_OAUTH_TOKEN instead of the generic BOT_BOTTLE_OAUTH_TOKEN, and make the auth section explicit that this env var is for bottles using the Claude agent provider.

Re #732: Agreed. I will update the Claude-provider examples/docs to use `BOT_BOTTLE_CLAUDE_OAUTH_TOKEN` instead of the generic `BOT_BOTTLE_OAUTH_TOKEN`, and make the auth section explicit that this env var is for bottles using the Claude agent provider.
didericis added 1 commit 2026-05-28 18:20:18 -04:00
docs(agent): clarify claude oauth env
test / unit (pull_request) Successful in 29s
test / integration (pull_request) Successful in 43s
cdb1870b1c
didericis added 1 commit 2026-05-28 18:33:32 -04:00
fix(dashboard): quiet docker polling errors
test / unit (pull_request) Successful in 29s
test / integration (pull_request) Successful in 41s
7f3998e79e
didericis added 1 commit 2026-05-28 18:45:08 -04:00
fix(dashboard): tolerate missing manifest
test / unit (pull_request) Successful in 25s
test / integration (pull_request) Successful in 44s
c4449001d1
didericis added 1 commit 2026-05-28 18:49:39 -04:00
fix(smolmachines): build sidecar image before launch
test / unit (pull_request) Successful in 26s
test / integration (pull_request) Successful in 39s
43cd83d77b
didericis added 1 commit 2026-05-28 19:00:53 -04:00
fix(agent): hide auth placeholder env in preflight
test / unit (pull_request) Successful in 31s
test / integration (pull_request) Successful in 55s
9399626ba6
didericis added 1 commit 2026-05-28 19:05:01 -04:00
fix(egress): remove implicit provider routes
test / unit (pull_request) Successful in 33s
test / integration (pull_request) Successful in 58s
c31845a5b8
didericis added 1 commit 2026-05-28 19:09:09 -04:00
fix(pipelock): disable bip39 detector by default
test / unit (pull_request) Successful in 35s
test / integration (pull_request) Successful in 57s
3299674c30
didericis added 1 commit 2026-05-28 19:20:13 -04:00
feat(pipelock): allow route tls passthrough policy
test / unit (pull_request) Successful in 37s
test / integration (pull_request) Successful in 58s
bcadc07d09
didericis added 1 commit 2026-05-28 19:32:48 -04:00
fix(pipelock): allow route ssrf ip policy
test / unit (pull_request) Successful in 28s
test / integration (pull_request) Successful in 44s
fed006441d
didericis added 1 commit 2026-05-28 19:45:04 -04:00
fix(manifest): allow ip git upstreams
test / unit (pull_request) Successful in 27s
test / integration (pull_request) Successful in 42s
1f0434bffc
didericis added 1 commit 2026-05-28 19:51:03 -04:00
fix(git): rewrite logical ip upstream aliases
test / unit (pull_request) Successful in 27s
test / integration (pull_request) Successful in 41s
f86349ca92
didericis added 1 commit 2026-05-28 20:00:11 -04:00
fix(git): mount git-gate known hosts
test / unit (push) Successful in 36s
test / integration (push) Successful in 57s
test / unit (pull_request) Successful in 32s
test / integration (pull_request) Successful in 59s
c854db87c6
didericis merged commit c854db87c6 into main 2026-05-28 20:04:41 -04:00
didericis deleted branch prd-0026-agent-provider-templates 2026-05-28 20:04:42 -04:00
Sign in to join this conversation.