Build agents
OpenAI-compatible clients
Code that calls OpenAI or OpenRouter switches to MorphScreen with a new base address and one header. Answers come back in our format, checked and repaired.
The API speaks OpenAI's chat completions, OpenRouter's flavour: streaming, usage with cost, fallback models, OpenRouter's provider settings. Code written for OpenAI's SDK or OpenRouter's switches by its base address and one header, and the rest stays as it is.
On your own OpenRouter key
Any model on OpenRouter runs on your own key. It goes to OpenRouter and nowhere else, never stored or logged.
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.morphscreen.com/v1",
apiKey: process.env.OPENROUTER_API_KEY,
defaultHeaders: { "X-MorphScreen-Key": process.env.MORPHSCREEN_KEY },
});
const stream = await client.chat.completions.create({
model: "anthropic/claude-sonnet-4.6",
stream: true,
messages: [{ role: "user", content: "Compare three running shoes under $120" }],
});
for await (const chunk of stream) process.stdout.write(chunk.choices[0]?.delta?.content ?? "");import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.morphscreen.com/v1",
api_key=os.environ["OPENROUTER_API_KEY"],
default_headers={"X-MorphScreen-Key": os.environ["MORPHSCREEN_KEY"]},
)On the model in your plan
The model included in your plan needs no OpenRouter key: send no Authorization header at all. OpenAI's Node SDK always adds one, so turn it off:
const client = new OpenAI({
baseURL: "https://api.morphscreen.com/v1",
apiKey: "unused",
defaultHeaders: { "X-MorphScreen-Key": process.env.MORPHSCREEN_KEY, Authorization: null },
});
// model: "deepseek/deepseek-v4.1-flash"From Python, call the API without the SDK (Python), since any Authorization header is taken as an OpenRouter key.
OpenRouter's own SDK
import { OpenRouter } from "@openrouter/sdk";
import { HTTPClient } from "@openrouter/sdk/lib/http.js";
const httpClient = new HTTPClient();
httpClient.addHook("beforeRequest", (req) => {
const r = new Request(req);
r.headers.set("X-MorphScreen-Key", process.env.MORPHSCREEN_KEY);
return r;
});
const openrouter = new OpenRouter({ apiKey: process.env.OPENROUTER_API_KEY, serverURL: "https://api.morphscreen.com/v1", httpClient });What changes
- The answer is in our format, and the API's system prompt goes before your messages (The system prompt).
- The last streamed chunk carries the core's verdict, and the repaired text when a repair was needed (Validation and repair).
- OpenRouter's errors come back as your SDK's own error classes, with OpenRouter's status: a 402 when your OpenRouter credit runs out, a 429 with its wait.
- Options go in a
morphscreenfield of the request:packs,components,images,photos,repair(the reference).
To draw the text, pass it to the web SDK's createAnswer or <Answer>, or render it on your server with /v1/render.