ruflo-adr/agent_execute: the Anthropic provider hardcodes api.anthropic.com and ignores ANTHROPIC_BASE_URL, so it cannot reach a Messages-API gateway (the OpenRouter provider can)
- Dominant language
- TypeScript
- Stars
- 72.7k
- Forks
- 8.6k
- Avg merge
- 2d 23h
- Merged PRs (30d)
- 83
Description
`agent-execute-core.js` hardcodes the Anthropic endpoint and reads only `ANTHROPIC_API_KEY`, so ruflo's Messages-API provider cannot be pointed at any Anthropic-compatible gateway — even though Claude Code, the official SDKs, and the `ant` CLI all honour `ANTHROPIC_BASE_URL` / `ANTHROPIC_AUTH_TOKEN`.
`src/mcp-tools/agent-execute-core.js`:
```js
// :104
const anthropicKey = process.env.ANTHROPIC_API_KEY;
...
// :155
if (!anthropicKey) {
return { success: false,
error: 'No LLM provider configured. Set ANTHROPIC_API_KEY (Tier-3), OPENROUTER_API_KEY (#2042), or OLLAMA_API_KEY (Tier-2 — #1725).' };
}
...
// :166
const res = await fetch('https://api.anthropic.com/v1/messages', {
method: 'POST',
headers: { 'x-api-key': anthropicKey, 'anthropic-version': '2023-06-01', 'content-type': 'application/json' },
```
## Why this matters
A common setup routes Claude Code through a local Messages-API-compatible proxy — set `ANTHROPIC_BASE_URL` to the proxy and `ANTHROPIC_AUTH_TOKEN` to a placeholder, because the proxy holds the real credential. Claude Code works fine. ruflo cannot participate at all:
- `ANTHROPIC_API_KEY` is deliberately unset (there is no key to set — that is the point of the proxy), so `agent_execute` fails closed with *"No LLM provider configured"*.
- Even with a dummy value in `ANTHROPIC_API_KEY`, the hardcoded `https://api.anthropic.com/v1/messages` sends the request to Anthropic, which rejects it.
So there is no configuration that makes the Anthropic provider reach a gateway.
## The inconsistency
The **OpenRouter** provider in the same file is fully configurable:
```js
// :127
baseUrl: process.env.OPENROUTER_BASE_URL || persistedOpenRouter?.baseUrl || 'https://openrouter.ai/api',
```
Setting `RUFLO_PROVIDER=openrouter` + `OPENROUTER_BASE_URL=` does work as a workaround (verified — a proxy serving the OpenAI-compatible `/v1/chat/completions` returns normally). But it is **fail-open**: if `OPENROUTER_BASE_URL` is ever unset while `OPENROUTER_API_KEY` is present, requests silently go to `https://openrouter.ai/api` instead of the intended local endpoint. For anyone using a proxy specifically to control where traffic goes, a silent third-party fallback is the wrong failure mode.
The Anthropic provider having no base-URL override while the OpenRouter one does looks unintentional rather than by design.
## Reproduction
```sh
unset ANTHROPIC_API_KEY
export ANTHROPIC_BASE_URL=http://localhost:4141 # any Messages-API-compatible gateway
export ANTHROPIC_AUTH_TOKEN=dummy
# agent_spawn, then agent_execute
# → {"success": false, "error": "No LLM provider configured. Set ANTHROPIC_API_KEY ..."}
```
## Suggested fix
Two changes, both additive and backward-compatible — an unset `ANTHROPIC_BASE_URL` keeps today's behaviour exactly:
```js
// :104 — accept the token variable the rest of the Anthropic ecosystem uses
const anthropicKey = process.env.ANTHROPIC_API_KEY || process.env.ANTHROPIC_AUTH_TOKEN;
// :166 — resolve the endpoint, defaulting to the current hardcoded value
const res = await fetch(
(process.env.ANTHROPIC_BASE_URL || 'https://api.anthropic.com').replace(/\/+$/, '') + '/v1/messages',
{ ... }
);
```
Verified against a local Messages-API proxy: with only `ANTHROPIC_BASE_URL` + `ANTHROPIC_AUTH_TOKEN` set (`ANTHROPIC_API_KEY`, `RUFLO_PROVIDER` and `OPENROUTER_BASE_URL` all unset), `agent_execute` returns `{"success": true, "model": ""}`. No request reaches `api.anthropic.com`.
Header note: `x-api-key` needed no change — the gateway tested accepts it. If you would rather send `Authorization: Bearer` when the credential comes from `ANTHROPIC_AUTH_TOKEN`, that is a reasonable refinement, but it was not required.
## Related
`resolveAnthropicModel` maps `inherit` → `DEFAULT_ANTHROPIC_MODEL` rather than to anything environment-derived. That is defensible, but the alias reads as "inherit from the environment" and does not — worth a doc line, or an alias that actually consults `ANTHROPIC_MODEL`.
Versions: `@claude-flow/cli` 3.38.20, node 22, macOS.
Contributor guide
Research direction
Start in src/mcp-tools/agent-execute-core.js at the Anthropic configuration and fetch call, then reproduce the documented agent_spawn/agent_execute setup against a local Messages-API proxy. Done means the provider accepts the documented environment variables, uses the configured gateway without contacting api.anthropic.com, and preserves the current default endpoint when no override is set.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- ai, backend-api-design
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 84/100