feat: ACP providers for claude code and codex#6605
Conversation
|
@michaelneale @baxen @alexhancock I may be out of time this week and I wanted this to be a collaborative thing anyway. if either of you want to work on this branch it would be gratefully accepted. The main thing I found is that I can't really test claude because I downgraded my subscription and so get a wait for problem later. I started testing codex, and first ran into the npx wrapper not working out, so was doign a pattern to cache the rust binary to run directly, similar to how zed works around the same issue. Hopefully somethjign like this works in the future for claude and codex and when things work well enough we can kill the. CLI providers. Anyway I'm done for at least a day I think so it is safe to work on if one feels like it. |
|
nice - tested with claude and codex - did see odd artifacts like: but it did work and call things - nice! |
|
tagging @DOsinga as this adds a crate etc, but seems to work nice. this will replace the CLI providers. |
|
Nice! In https://discord.com/channels/1287729918100246654/1408153538537721966/1463661278202695754 I had moved the ACP server code to the I love the idea of having ACP wrappers for Claude Code and Codex but wonder if there are ones available already we could use? cc @benbrandt |
|
@alexhancock on
So, this uses the same wrappers as zed uses and maintains I ran into a problem using the npm launched in codex-acp, remember codex-acp is actually a rust binary. Then I inspected the zed code and found they are extracting it from the github repo. So, we are doing the same more or less here. One thing to follow-up on is once the ACP registry is live, this code will be a lot easier. If your question is about us needed mappings, that's because this change is about goose -> acp and we are not making a large change to goose itself. So we need to adapt our concepts of approval mode etc to these providers who are not 100pct consistent. that's because ACP is designed to propagate approval and mode choices all the way to the client. Currently Goose CLI, UI etc is not designed to work with third party modes. Hence, we have some glue that we need until that's the case. OTOH for clients calling into goose, nothing changed here. This PR is about adapting our provider infrastructure so that we can have an option besides completely bespoke "CLI provider" glue. Hope these pointers help! p.s. goose is lacking modularity for shared packages which is why there's crate re-org. If there was a goose-api crate, and types like provider etc were there, we'd not have the dependency cycle issues which forced into goose-acp-server and goose-acp-client. Since goose isn't used as a library formally anyway, this is tech debt we can clean up and prevent most things getting stuck in goose crate for the same reason. |
|
rebase of this is a bear due to intentional session-id tightening. I got it. TL;DR; since ACP agents own the sessions, we need to rejig a bit to not fight over the ID. Right now ACP spec does not allow BYO id you have to get one back from the agent. correlation mapping is not great because ops like terminal cross processes and that would force us to add an external id into the DB. The other way is to rejig so that initial session ID creation algo can be overridden based on the provider type, defaulting to normal session manager. So, for ACP, we create a session then get its id and insert it into the normal session manager. That allows us to have 1-1 correlation of session ID. Next is how to do cold resume of session... depending on agent it is load or resume and there is nuance on how to handle this, but we have the code to handle both. If/when ACP changes the session new/load/resume we can replumb, but anyway while what I describe sounds creaky it isn't more troublesome than permission managing. I have a plan for this and the next push will implement it and update the desc with a diagram how. |
|
Yes we manage the claude and codex wrappers. Though for clarity:
Regarding codex's npx usage... I worked with another team to add npm support. We don't use it ourselves, but I would hope it works. If it needs to be fixed, and you can provide more information, we can also do that so you can use that if you'd rather |
|
@benbrandt on codex-acp I ran into unexplained unresponsiveness, which could be due to internal bootstrapping perhaps. I tried several times despite |
0c4bc41 to
505e47e
Compare
|
update on this. This branch is really expensive to maintain, particularly as there are so many model gaps between the provider design and ACP sessions. Each time I touch this I lose several hours and it still isn't a great bridge between provider and ACP. I'd like folks to pipe in if this should ship as-is or continue at all. I think Provider -> ACP is really awkward and the days spent on this direction while instructive could have been better spent making a whole new API backend. |
|
I'm going to flatten this stuff into the goose crate as working around it is a cure worse than the disease. that we had a goose-acp crate at all only worked for the server side as it did't need access to goose core types, which are mixed with impl and cause a lot of tension that results in a bit of a mess. best path out is to just keep adding things to goose core crate until we work out modularity as this isn't about ACP rather ACP is just another example of the same tension, which is inability to implement a provider neatly except inside goose crate. |
cb16395 to
4b78e8f
Compare
|
once this is in probably for real rebase. this PR levels non-acp claude and codex and what they need to stitch MCP through. this will make the ACP variants more straightforward to compare as they are very similar to CLI providers #6972 For this reason I've been toying with us calling the formerly unqualified Provider "LLM Provider" and either CLI or ACP as "Agentic Provider" |
4b78e8f to
919285d
Compare
|
I've had something personal come up, I've pushed the latest code I have and if someone can/desires to take this over please do. I updated the PR desc. |
|
919285d to
58c14dd
Compare
|
this is still in draft, but looks very sweet - can we get this in @michaelneale & @codefromthecrypt ? |
58c14dd to
d2f8390
Compare
c408d1d to
25903ce
Compare
|
@DOsinga @michaelneale @lifeizhou-ap as soon as #7738 merges I'll rebase and put this open for review as it works for most use cases now. |
17cca93 to
89b8d72
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 89b8d722ef
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7e68ab3b13
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1275c4b3f8
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
alexhancock
left a comment
There was a problem hiding this comment.
Looks great!
Looks like minor test & lint failure but other than that good
error: couldn't read `crates/goose-acp/tests/common_tests/../test_data/openai_image_attachment.txt`: No such file or directory (os error 2)
Error: --> crates/goose-acp/tests/common_tests/mod.rs:330:13
|
330 | include_str!("../test_data/openai_image_attachment.txt"),
Goose can now use any ACP agent as a provider via stdio transport. - claude-acp and codex-acp wired as concrete providers - MCP extension passthrough (agents receive goose MCP servers) - Permission routing (same as claude-code CLI provider) - Model listing and switching via session/new and session/set_model Signed-off-by: Adrian Cole <adrian@tetrate.io>
Signed-off-by: Adrian Cole <adrian@tetrate.io>
1275c4b to
4ff0471
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4ff04716d0
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| _model_config: &ModelConfig, | ||
| session_id: &str, |
There was a problem hiding this comment.
Apply requested model to ACP session before prompting
The stream path ignores the requested model_config (it is explicitly _model_config) and immediately prompts the cached ACP session, so non-default model selections are never propagated via session/set_model before inference. This causes users who set a model at startup or switch models to silently continue running on the ACP session’s previous/default model; fresh evidence is that a repo-wide search shows AcpProvider::set_model is only called in test fixtures and not from production provider flow.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 32cf3f4285
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| } | ||
|
|
||
| async fn fetch_supported_models(&self) -> Result<Vec<String>, ProviderError> { | ||
| let response = self.ensure_session(None).await?; |
There was a problem hiding this comment.
Reuse an ACP session when fetching supported models
fetch_supported_models calls ensure_session(None), but ensure_session only memoizes sessions when a non-None Goose session ID is provided, so every model-list refresh creates a brand new ACP session. In long-lived clients that poll or reopen model lists, this steadily accumulates orphan ACP sessions (there is no corresponding close path here), which increases memory/state usage and can eventually degrade or break provider behavior.
Useful? React with 👍 / 👎.
|
I will follow up with a doc PR. Thanks for the patience! |
|
docs #7800 |
* main: (45 commits)
fix: resolve {{ recipe_dir }} in nested sub-recipe paths during secret discovery (#7797)
Add @DOsinga as CODEOWNER for documentation (#7799)
feat: Add summarize tool for deterministic reads (#7054)
fix(api): use camelCase in CallToolResponse and add type discriminators to ContentBlock (#7487)
feat: ACP providers for claude code and codex (#6605)
chore(deps): bump express-rate-limit from 8.2.1 to 8.3.0 in /evals/open-model-gym/mcp-harness (#7703)
feat(openai): capture reasoning summaries from responses API (#7375)
Fix some dependencies (#7794)
fix: improve keyring availability error detection (#7766)
feat: add MiniMax provider with Anthropic-compatible API (#7640)
feat: add Tensorix as a declarative provider (#7712)
fix(security): remove insecure default secret from GOOSE_EXTERNAL_BACKEND (#7783)
refactor: Convert Tanzu provider to declarative JSON config (#7124)
replaces https://github.com/block/goose/pull/7340/changes (#7786)
feat(summon): make skill supporting files individually loadable via load() (#7583)
Keep toast open on failed extension (#7771)
fix(ui-desktop): unify path resolution around GOOSE_PATH_ROOT (#7335)
fix: pass OAuth scopes to DCR and extract granted_scopes from token response (#7571)
fix: write to real file if config.yaml is symlink (#7669)
fix: preserve pairings when stopping gateway (#7733)
...
* main: (69 commits)
fix: resolve {{ recipe_dir }} in nested sub-recipe paths during secret discovery (#7797)
Add @DOsinga as CODEOWNER for documentation (#7799)
feat: Add summarize tool for deterministic reads (#7054)
fix(api): use camelCase in CallToolResponse and add type discriminators to ContentBlock (#7487)
feat: ACP providers for claude code and codex (#6605)
chore(deps): bump express-rate-limit from 8.2.1 to 8.3.0 in /evals/open-model-gym/mcp-harness (#7703)
feat(openai): capture reasoning summaries from responses API (#7375)
Fix some dependencies (#7794)
fix: improve keyring availability error detection (#7766)
feat: add MiniMax provider with Anthropic-compatible API (#7640)
feat: add Tensorix as a declarative provider (#7712)
fix(security): remove insecure default secret from GOOSE_EXTERNAL_BACKEND (#7783)
refactor: Convert Tanzu provider to declarative JSON config (#7124)
replaces https://github.com/block/goose/pull/7340/changes (#7786)
feat(summon): make skill supporting files individually loadable via load() (#7583)
Keep toast open on failed extension (#7771)
fix(ui-desktop): unify path resolution around GOOSE_PATH_ROOT (#7335)
fix: pass OAuth scopes to DCR and extract granted_scopes from token response (#7571)
fix: write to real file if config.yaml is symlink (#7669)
fix: preserve pairings when stopping gateway (#7733)
...
Summary
Goose can now use any ACP agent as a provider. This adds
AcpProvider, a genericProviderimplementation that speaks the ACP protocol over stdio transport, and wires up two concrete providers:claude-acpcodex-acpAdding more ACP agents is just a new
ProviderDefand configuration such as the binary and permissions mappings.Key capabilities:
--with-extensionservers)claude-codeCLI provider)session/newandsession/set_modelKey limitations which are punted to prevent this PR taking forever:
Type of Change
AI Assistance
Testing
Provider integration tests
Claude ACP
Codex ACP
$ npm install -g @zed-industries/codex-acp changed 2 packages in 569ms