Run ai-hedge-fund on a custom OpenAI-compatible base URL.

Updated 2026-07-16

ai-hedge-fund builds its OpenAI models with LangChain's ChatOpenAI and reads the base URL from OPENAI_API_BASE. Set it to https://api.apisrouter.com/v1, export one key, and every analyst agent in the fund routes through a single endpoint.

Quick answer: OPENAI_API_BASE plus one key.

ai-hedge-fund's OpenAI provider is instantiated as ChatOpenAI(model=model_name, api_key=api_key, base_url=base_url), and that base_url comes from os.getenv("OPENAI_API_BASE") in src/llm/models.py. So the override is two lines in .env: point OPENAI_API_BASE at https://api.apisrouter.com/v1 and set OPENAI_API_KEY to your gateway key. Every model that runs through the OpenAI provider now posts to the gateway. Note the variable name carefully: it is OPENAI_API_BASE, the LangChain-era convention, not OPENAI_BASE_URL. Exporting the wrong one is silently ignored and requests keep going to api.openai.com, which is the most common way this setup appears not to work.

OPENAI_API_BASE=https://api.apisrouter.com/v1
OPENAI_API_KEY=sk-APIsRouter-...
FINANCIAL_DATASETS_API_KEY=...   # market data, unrelated to the LLM endpoint

How ai-hedge-fund picks a model and a provider.

ai-hedge-fund (virattt on GitHub, roughly 62K stars) simulates a fund as a committee of agents: analyst personas modeled on well-known investors, plus valuation, sentiment, fundamentals, and technicals agents, feeding a risk manager and a portfolio manager that produce the final signals. All of them share one model choice per run, so a single run multiplies your model decision across every agent and every ticker. Model selection has two paths. Interactively, running poetry run python src/main.py --ticker AAPL,MSFT,NVDA with no model flag opens a questionary picker. Scripted, the --model flag takes a model name, but only names that exist in the repo's model registry: find_model_by_name() looks the string up in src/llm/api_models.json, and each registry entry carries display_name, model_name, and provider. If the lookup fails, the CLI does not guess a provider; it falls back to the interactive picker, which matters for automation because an unknown id turns a scripted run into one that sits waiting for keyboard input. The provider field is what decides routing. Entries marked OpenAI go through ChatOpenAI and honor OPENAI_API_BASE; entries marked Anthropic go through ChatAnthropic and ANTHROPIC_API_KEY, bypassing your base URL entirely. That is the key insight for gateway routing: the provider column selects the client and therefore the endpoint, independent of who actually made the model.

Full setup: .env plus a registry entry per gateway model.

For models the registry already lists under the OpenAI provider, the .env override alone is enough; the model string is passed through to the endpoint as-is. To run a Claude, DeepSeek, or Qwen id through the gateway on the same key, add an entry to src/llm/api_models.json with the catalog id as model_name and, crucially, "OpenAI" as the provider. Provider selects the client, so an OpenAI-marked entry routes through ChatOpenAI and your OPENAI_API_BASE even though the model itself is not an OpenAI model. The entry then appears in the interactive picker and resolves via --model in scripts. This is a three-line JSON edit in your clone, not a code change, and it is the documented shape the registry already uses. Keep the provider-native entries in mind as the contrast: selecting a registry model marked Anthropic will look for ANTHROPIC_API_KEY and go straight to Anthropic's endpoint. If your intent is one gateway key for everything, run your models through OpenAI-marked entries and you can leave the per-vendor keys unset entirely.

{
  "display_name": "Claude Sonnet 4.6 (gateway)",
  "model_name": "claude-sonnet-4-6",
  "provider": "OpenAI"
},
{
  "display_name": "DeepSeek V4 Pro (gateway)",
  "model_name": "deepseek-v4-pro",
  "provider": "OpenAI"
}

Choosing a model for an agent committee.

Because the registry makes every candidate addressable behind one flag, the honest evaluation is empirical: run the same tickers and dates through two or three models and compare the signals and the spend. The per-key usage view prices each sweep for you, which turns model choice from a debate into a measurement.

  • One run is many verdicts. Every analyst persona reasons over the same filings and price data per ticker, so the model choice is multiplied by the agent count times the ticker count. A frontier reasoning id (claude-opus-4-7, gpt-5.5) raises the quality of every verdict at a correspondingly multiplied token bill.
  • claude-sonnet-4-6 is the sensible default: strong enough that persona reasoning stays coherent over long fundamental context, priced for runs that fan out across a dozen agents and a basket of tickers.
  • deepseek-v4-pro and qwen3.7-max are worth benchmarking for wide sweeps, where the per-run price gap compounds across every backtest date.
  • Whatever you pick, pin it. Signals from different snapshots of a moving model are not comparable across a backtest window; use exact ids and record the model string next to the results like a random seed.

Pay-as-you-go · transparent per-model pricing

Selected models are priced below official list prices. Exact input, output, cache, and per-request prices are shown for each model.

ModelOfficial PriceOur Price
Claude Opus 4.7$5.00 / $25.00 per M$4.00 / $20.00 per M
Claude Sonnet 4.6$3.00 / $15.00 per M$2.40 / $12.00 per M
GPT-5.5$5.00 / $30.00 per M$4.00 / $24.00 per M
DeepSeek V4 Pro$0.43 / $0.87 per M$0.39 / $0.78 per M
Qwen 3.7 Max$2.50 / $7.50 per M$2.25 / $6.75 per M

The failure modes specific to ai-hedge-fund.

The wrong environment variable. This repo reads OPENAI_API_BASE. OPENAI_BASE_URL, the variable other tools use, is not consulted, and setting it does nothing except convince you the override is broken. If requests still hit api.openai.com, check the variable name before anything else. --model with an unregistered id. find_model_by_name() only knows entries in api_models.json. Pass a catalog id that is not registered and the CLI prints a not-found message and drops into the interactive picker, which in a cron job or CI run means a silent hang, not an error exit. Register the id first; then scripted runs resolve it deterministically. Provider-marked entries bypassing the gateway. Picking a registry model whose provider is Anthropic, Google, or DeepSeek routes through that vendor's native client and key. If you expected the run to appear in your gateway usage log and it did not, the provider column of the model you picked is the explanation. Data errors masquerading as LLM errors. Price and fundamentals data come from the financial-data API configured by FINANCIAL_DATASETS_API_KEY, a wholly separate service. A missing or exhausted data key fails the run before or between LLM calls, and the traceback can read like a model problem. The two credentials fail independently; debug them independently. Interactive prompts in automation. Even with everything configured, forgetting the --model flag opens the picker. For unattended runs, always pass --model with a registered id.

Who routes ai-hedge-fund through a gateway.

  • Backtesters sweeping tickers and date ranges, where an agent committee per ticker per date makes token spend the dominant cost and per-key usage the natural ledger.
  • Researchers comparing model verdicts. The same run under two model ids is a flag change, and signal disagreement between models is itself interesting data.
  • Builders extending the repo with new agents who want one endpoint and one key underneath however many personas they add.
  • Developers who want Claude or DeepSeek reasoning inside a repo whose cleanest routing path is OpenAI-shaped, without maintaining a vendor key per provider entry.
  • Developers without access to a given vendor's billing. Top-up based access with no card requirement removes the per-provider sign-up dependency.

Verify the endpoint and debug the first run.

Confirm the gateway serves the ids you registered before launching a run; registry model_name strings must match served ids exactly. The first-run failure ladder: a 401 means OPENAI_API_KEY is not the gateway key in the environment poetry actually launched with. A model-not-found error from the gateway means the registry entry's model_name has a typo relative to /v1/models. A run that stops to ask for input means the --model string missed the registry. A vendor-key error (Anthropic, Google) means the selected entry's provider is not OpenAI. And a data-shaped traceback before any model output points at FINANCIAL_DATASETS_API_KEY, not the LLM path. Once a run completes, the APIsRouter console shows per-request model, token counts, and spend. A committee run is dozens of calls across analysts, risk, and portfolio stages, and the usage view is how you see what one decision actually costs before you scale it into a sweep.

curl -s https://api.apisrouter.com/v1/models \
  -H "Authorization: Bearer $OPENAI_API_KEY" | head -50

FAQ

Which environment variable sets a custom base URL for ai-hedge-fund?

OPENAI_API_BASE. The OpenAI provider in src/llm/models.py builds ChatOpenAI with base_url=os.getenv("OPENAI_API_BASE"). OPENAI_BASE_URL is not read by this repo, so use the API_BASE spelling exactly.

Can ai-hedge-fund run Claude or DeepSeek models through one key?

Yes, by registering the id in src/llm/api_models.json with provider set to "OpenAI". Provider selects the client, so an OpenAI-marked entry routes through ChatOpenAI and your OPENAI_API_BASE, and the catalog id is passed through to the gateway as a plain string.

Why does --model drop me into an interactive picker?

The --model value is looked up with find_model_by_name() against api_models.json. Unknown ids are not guessed; the CLI prints a not-found message and opens the picker. Add a registry entry for the id and scripted runs resolve it without prompting.

Do I still need ANTHROPIC_API_KEY or other vendor keys?

Not for gateway-routed models. Vendor keys are only consulted by registry entries marked with that vendor's provider. If every model you run is registered under the OpenAI provider, the gateway key is the only LLM credential the run needs.

Does the market-data setup change when I change the LLM endpoint?

No. Price and fundamentals data flow through the financial-data API configured by FINANCIAL_DATASETS_API_KEY, which is independent of the LLM base URL. The two credentials fail in different phases of a run, so debug them separately.

How expensive is one ai-hedge-fund run?

It scales with agents times tickers: each analyst persona, plus risk and portfolio management, reasons per ticker. Single-basket runs typically land in the tens to hundreds of thousands of tokens, and backtest sweeps multiply that by the date grid. The per-key usage view gives the exact figure per run.