Skip to content

Point your agent at it

Every agent that lets you override its base URL can talk through hlid. Two environment variables cover most of them.

Anthropic-dialect agents

Claude Code, Aider in anthropic mode, and anything built on the Anthropic SDK:

bash
export ANTHROPIC_BASE_URL=http://localhost:8080
export ANTHROPIC_API_KEY=sk-hlid-whatever   # your hlid auth_key, or anything if auth is off

The agent will call /v1/messages on hlid. Whatever model it asks for, the registry decides where the request actually goes — including to an OpenAI-dialect backend, translated on the way.

OpenAI-dialect agents

The OpenAI SDK, Continue, Cursor, Aider in openai mode:

bash
export OPENAI_BASE_URL=http://localhost:8080
export OPENAI_API_KEY=sk-hlid-whatever

SDKs

python
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8080/v1", api_key="sk-hlid-local")
resp = client.chat.completions.create(
    model="llama-3-70b",   # routed by your hlid registry
    messages=[{"role": "user", "content": "Hello!"}],
)
python
from anthropic import Anthropic

client = Anthropic(base_url="http://localhost:8080", api_key="sk-hlid-local")
resp = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=200,
    messages=[{"role": "user", "content": "Hello!"}],
)
ts
import OpenAI from 'openai'

const client = new OpenAI({
  baseURL: 'http://localhost:8080/v1',
  apiKey: 'sk-hlid-local',
})
const resp = await client.chat.completions.create({
  model: 'llama-3-70b',
  messages: [{ role: 'user', content: 'Hello!' }],
})

Smoke test with curl

bash
# Passthrough: OpenAI dialect in → OpenAI-dialect backend (no translation)
curl -s http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model": "gpt-4o", "messages": [{"role": "user", "content": "Say hi"}]}' | jq .

# Cross-dialect: Anthropic dialect in → OpenAI-dialect backend (auto-translated)
curl -s http://localhost:8080/v1/messages \
  -H "Content-Type: application/json" \
  -d '{"model": "claude-sonnet-4-20250514", "max_tokens": 100, "messages": [{"role": "user", "content": "Say hi"}]}' | jq .

# Streaming (add "stream": true)
curl -s http://localhost:8080/v1/messages \
  -H "Content-Type: application/json" \
  -d '{"model": "claude-sonnet-4-20250514", "max_tokens": 100, "stream": true, "messages": [{"role": "user", "content": "Tell me a joke"}]}'

The model name is the router

Agents don't know about backends — they just name a model. Your registry turns that name into a destination. A useful pattern: keep the model names your agents already use, and add one [[backends]] entry per family. No agent-side changes when a backend moves.

MIT licensed · built at the workbench