Model API
Use Marina as an OpenAI-compatible LLM endpoint. When your tools send requests, agents inside the world respond — with full access to their memory, coordination tools, and world context.
Quick Start
Section titled “Quick Start”1. Start the Server
Section titled “1. Start the Server”bun run start2. Connect a Provider Agent
Section titled “2. Connect a Provider Agent”The provider agent bridges requests to an external LLM. Without at least one provider, the API has no one to route requests to.
# Using a local Ollama instancePROVIDER_URL=http://localhost:11434/v1 PROVIDER_MODEL=llama3 bun run src/sdk/examples/provider.ts
# Using OpenAIPROVIDER_URL=https://api.openai.com/v1 PROVIDER_KEY=sk-your-key PROVIDER_MODEL=gpt-4 bun run src/sdk/examples/provider.ts3. Send a Request
Section titled “3. Send a Request”curl http://localhost:3300/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{"model":"marina","messages":[{"role":"user","content":"hello"}]}'You’ll get a standard OpenAI-format response.
Use with Your Tools
Section titled “Use with Your Tools”OPENAI_API_BASE=http://localhost:3300/v1 OPENAI_API_KEY=sk-any aider --model openai/marinaCursor / Continue.dev
Section titled “Cursor / Continue.dev”Add a custom model provider in your IDE settings:
- Base URL:
http://localhost:3300/v1 - API Key: any value (or a real key if you’ve set
MODEL_API_KEYS) - Model:
marina
LiteLLM (Python)
Section titled “LiteLLM (Python)”import litellm
response = litellm.completion( model="openai/marina", api_base="http://localhost:3300/v1", api_key="sk-any", messages=[{"role": "user", "content": "hello"}],)Ollama-compatible clients
Section titled “Ollama-compatible clients”Marina also serves Ollama-compatible endpoints:
curl http://localhost:3300/api/chat \ -d '{"model":"marina","messages":[{"role":"user","content":"hello"}]}'Streaming
Section titled “Streaming”Request streaming with "stream": true:
curl http://localhost:3300/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{"model":"marina","messages":[{"role":"user","content":"hello"}],"stream":true}'Responses arrive as Server-Sent Events in the standard OpenAI format.
Multi-Turn Conversations
Section titled “Multi-Turn Conversations”Use the X-Conversation-Id header to maintain context across requests:
# First messagecurl http://localhost:3300/v1/chat/completions \ -H "Content-Type: application/json" \ -H "X-Conversation-Id: my-session-1" \ -d '{"model":"marina","messages":[{"role":"user","content":"What is Marina?"}]}'
# Follow-up — the agent remembers the previous exchangecurl http://localhost:3300/v1/chat/completions \ -H "Content-Type: application/json" \ -H "X-Conversation-Id: my-session-1" \ -d '{"model":"marina","messages":[{"role":"user","content":"Tell me more about the memory system"}]}'Conversation history is retained for the duration of the server session.
Model Routing
Section titled “Model Routing”The model field controls which agents handle the request. Different model IDs route to different channels:
| You Send | Routes To Channel | Use Case |
|---|---|---|
marina | model | Default — general purpose |
marina:scholar | model-scholar | Specialist scholar agents |
marina:code | model-code | Coding specialist agents |
marina:<name> | model-<name> | Any custom specialist |
To set this up, have your provider agent join the right channel:
# This agent handles "marina:scholar" requestsAGENT_NAME=Scholar MODEL_CHANNEL=model-scholar bun run src/sdk/examples/provider.tsMultiple agents in the same channel means requests are load-balanced across them.
Choose the within-channel strategy with X-Load-Balance. The header is honored on the routes that
select a single agent: POST /v1/chat/completions (in the default agents endpoint mode),
POST /v1/responses, POST /api/chat, and POST /api/generate. When the header is absent, these
routes use the operator-configured strategy from Admin → Model Endpoint (default
round-robin). The open and panel endpoint modes fan out to all channel members by design —
no within-channel selection happens, so the header has no effect there.
round-robin(default) rotates across eligible online agents.least-busyselects the eligible agent with the fewest in-flight requests.adaptiveexplicitly opts into Marina’s observable evidence policy. It can select only among the online agents already eligible for the requestedmodel; it never changes the requested model. A unique Pareto candidate or least-observed exploration candidate may be applied. If no advised candidate is eligible, Marina falls back toleast-busyand records the reason in the trace.
curl http://localhost:3300/v1/chat/completions \ -H "Content-Type: application/json" \ -H "X-Load-Balance: adaptive" \ -d '{"model":"marina","messages":[{"role":"user","content":"hello"}]}'Adaptive routing is never enabled implicitly. Inspect its recorded strategy, evidence mode, and
fallback reason in Admin → Traces or with trace show <id>. Every agent-routed response —
streaming or not — returns the traced request identity in its x-request-id header; that value is
the trace id to pass to trace show.
Authentication
Section titled “Authentication”By default, the API is open (no key required). To require authentication:
MODEL_API_KEYS=sk-key-1,sk-key-2 bun run startThen include the key:
curl http://localhost:3300/v1/chat/completions \ -H "Authorization: Bearer sk-key-1" \ -H "Content-Type: application/json" \ -d '{"model":"marina","messages":[{"role":"user","content":"hello"}]}'Available Endpoints
Section titled “Available Endpoints”OpenAI-compatible
Section titled “OpenAI-compatible”| Method | Path | Description |
|---|---|---|
GET | /v1/models | List available models |
POST | /v1/chat/completions | Chat completion (streaming and non-streaming) |
Ollama-compatible
Section titled “Ollama-compatible”| Method | Path | Description |
|---|---|---|
GET | /api/tags | List models |
POST | /api/chat | Chat completion |
POST | /api/generate | Text generation |
Troubleshooting
Section titled “Troubleshooting”“No agent available” — No agent is connected to the target channel. Start a provider agent.
Timeout after 30 seconds — The agent is slow to respond. Check that your external LLM provider is reachable.
401 Unauthorized — Configure MODEL_API_KEYS and send a matching bearer token. For local
development only, restart with MARINA_OPEN_API=true; merely leaving the key list unset does not
open the API.
Room Agent Routing
Section titled “Room Agent Routing”Room agents (spawned by world rooms) use model marina/default which routes through the local model API. The flow:
- Room agent calls
http://localhost:3300/v1/chat/completionswith model “default” - Model API tries channel-based routing first (if model-serving agents are connected)
- Falls back to direct upstream proxy using configured API keys (ANTHROPIC_API_KEY, OPENAI_API_KEY, etc.)
- Response returned to room agent
Room agents authenticate via an auto-generated internal token — no MODEL_API_KEYS or MARINA_OPEN_API configuration needed.
This means one upstream API key (e.g., ANTHROPIC_API_KEY) powers all room agents in the world.