PRD 0026: Agent Provider Templates #91
Reference in New Issue
Block a user
Delete Branch "prd-0026-agent-provider-templates"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
closes #90
Tracking PR for PRD 0026. Implementation will follow on this branch.
@@ -40,0 +48,4 @@remediation flows, and unit/integration tests covering exfiltration andsandbox escape scenarios.Current status: personal/small-team security tool, not yet enterpriseremove this paragraph
@@ -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, orCall the dockerfile for claude "Dockerfile.claude"
@@ -288,2 +306,4 @@GIT_AUTHOR_NAME: didericisagent_provider:template: claude # default; codex is also supportedIt 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?
Addressed both review comments in
8875d8c: removed the requested README status paragraph and renamed the Claude agent Dockerfile toDockerfile.claude, including the default provider/runtime references.@@ -0,0 +37,4 @@PROVIDER_CLAUDE: AgentProviderRuntime(template=PROVIDER_CLAUDE,command="claude",image="claude-bottle:latest",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.
@@ -26,3 +24,4 @@self.name = containerself._teardown = teardownself._prompt_path = prompt_path_in_containerself._agent_command = agent_commandwhy is this added twice? Once as
self._agent_command, another time asself.agent_command?@@ -86,2 +93,4 @@"codex" if agent_command == "codex" else "claude")def claude_argv(Am assuming this is agent agnostic now/should be renamed
agent_argv, correct?@@ -96,3 +104,1 @@if self._prompt_path:claude_tail += ["--append-system-prompt-file", self._prompt_path]claude_tail += argvclaude_tail = [self._agent_command]this claude specific naming in the function body should be fixed)
@@ -24,1 +19,4 @@prompt_path_in_container: str | None,*,agent_command: str = "claude",agent_prompt_mode: str = "claude_append_file",It seems like there are two different prompt modes:
codex_read_prompt_fileandclaude_append_file. Could they be shortened to justread_prompt_fileandappend_file? What makes them provider specific?Also would be nice to add type hints to available options here.
@@ -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)Change
capture_session_statetocapture_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)@@ -430,2 +479,3 @@@classmethoddef from_dict(cls, bottle_name: str, raw: object) -> "EgressConfig":def from_dict(cls, bottle_name: str, raw: object, *, provider_template: str = "claude",think we want to be more specific about what "provider_template" is throughout the code: rename variables like this to
agent_provider_template@@ -0,0 +54,4 @@```yamlagent_provider:template: codex # or claudedebating whether or not we should call this "type" instead of template...
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
claudethat declares bothagent_providerand Claude egress, with concrete bottles usingextends: claudeand adding task-specific env/git/routes. I will update the README/PRD examples around that pattern.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 #709: Correct. That surface is agent-agnostic now. I will rename it to
agent_argvand follow through withexec_agent/call-site/test renames, keeping temporary compatibility aliases only if the blast radius makes that safer for this PR.Re #707: The duplicate was a compatibility shortcut:
_agent_commandfor the handle internals,agent_commandfor dashboard/tmux code that introspects the running handle. I agree it is unnecessary. I will collapse this to one publicagent_commandattribute and use it internally too.Re #711: Agreed. I will rename the local variables and docstrings in that path from
claude_*toagent_*, while leaving only explicitly Claude-only state/transcript pieces named Claude.Re #717: Agreed. I will rename
provider_templatevariables/parameters toagent_provider_templatethroughout so the code matches the manifest shape and avoids the vague provider/template split.Re #715: Agreed. I will rename this to
capture_claude_session_stateand 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 #713: Yes, those modes are behavior-specific rather than provider-specific. I will rename them to
append_fileandread_prompt_file, and add explicit type hints for the accepted prompt modes so the runtime table is tighter.Re #719: My recommendation is to keep
template. In this designclaude/codexselects a bundled runtime template: command, image, Dockerfile, prompt behavior, and auth placeholder.typereads broader and could imply a stable taxonomy rather than a concrete launch template. I can change it if you prefer, but I would keeptemplateunless we want to rename the whole concept.Plan of attack after review feedback:
agent_provider.templateas the manifest key. No rename totype.claude/codexthat define bothagent_providerand provider egress/auth routes; task-specific bottles should useextends.claude-bottle->bot-bottle, including docs, CLI strings, image/container/network labels, state/cache paths, env vars, and the Python package/module rename fromclaude_bottletobot_bottle. No legacy env/state compatibility aliases needed.bot-bottle-claude:latestand matching Codex naming.claude_argv->agent_argv,exec_claude->exec_agent, localclaude_*variables ->agent_*, and update tests/call sites.agent_commandattribute.append_file,read_prompt_file) and add explicit type hints for allowed prompt modes.capture_session_statetocapture_claude_session_stateand add a FIXME noting current transcript/session capture is agent-specific; provider-neutral container-state freezing should be a follow-up spike.provider_templatevariables/params toagent_provider_templatethroughout.I will wait for approval before making these code changes.
@@ -421,3 +426,3 @@"upstream": "https://api.anthropic.com","auth_scheme": "Bearer","token_ref": "CLAUDE_BOTTLE_OAUTH_TOKEN","token_ref": "BOT_BOTTLE_OAUTH_TOKEN",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.
Re #732: Agreed. I will update the Claude-provider examples/docs to use
BOT_BOTTLE_CLAUDE_OAUTH_TOKENinstead of the genericBOT_BOTTLE_OAUTH_TOKEN, and make the auth section explicit that this env var is for bottles using the Claude agent provider.