Skip to main content

OpenRouter Chat Completion Agent

This integration calls OpenRouter's chat completions API with your input text and returns the model's text output. OpenRouter gives you access to many models behind a single key.

Required secrets

SecretWhat it is
OPENROUTER_API_KEYAPI key for calling OpenRouter chat completions.

Where to get the credentials

Generate an API key in your OpenRouter account settings, then store it as a project secret named OPENROUTER_API_KEY.

Turn support

Single-turn. Each evaluation case is sent as an independent request. For a conversational variant, use the OpenRouter Multi-Turn Chat Completion Agent.

Limitations and notes

  • The model and system prompt are set in the copied agent code. Edit the agent if you need to change them.
  • Calls are billed to your own OpenRouter account, subject to its quotas and rate limits.

How the agent works

The copied agent is a single JavaScript function. This walkthrough follows the real code so you can adapt the same pattern to point at a different service.

The entry point is process(input), where input is the per-case text the platform sends you:

export async function process(input) {
try {
const apiKey = String(env.OPENROUTER_API_KEY ?? "").trim();
const parsed = parseInput(input);
// ...

The secret is read from the ambient env object by key — env.OPENROUTER_API_KEY — and trimmed. See Required secrets for the key you must declare.

parseInput accepts either plain text or a JSON object. A bare string is used as-is; a JSON object lets a case override the prompt, model, and system prompt:

const parsed = JSON.parse(raw);
// ...
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
return {
text: String(parsed.text ?? parsed.prompt ?? parsed.input ?? "").trim(),
model: String(parsed.model ?? DEFAULT_MODEL).trim() || DEFAULT_MODEL,
system: String(
parsed.system ?? parsed.instructions ?? DEFAULT_SYSTEM_PROMPT,
).trim(),
};
}

buildMessages turns the parsed input into the chat-completions messages array, prepending a system message only when a system prompt is set:

const buildMessages = ({ text, system }) => {
const messages = [];
const systemPrompt = String(system ?? DEFAULT_SYSTEM_PROMPT).trim();

if (systemPrompt) {
messages.push({ role: "system", content: systemPrompt });
}

messages.push({ role: "user", content: text });
return messages;
};

The HTTP request is a POST with a Bearer auth header plus OpenRouter's attribution headers, and a JSON body of { model, messages }:

const response = await fetch(ENDPOINT, {
method: "POST",
headers: {
authorization: `Bearer ${apiKey}`,
"content-type": "application/json",
"HTTP-Referer": ATTRIBUTION_REFERER,
"X-Title": ATTRIBUTION_TITLE,
},
body: JSON.stringify({
model: parsed.model,
messages: buildMessages(parsed),
}),
});

The response text is parsed as JSON, then extractResponseText reads the first choice's message.content (a plain string, or an array of parts joined together):

const extractResponseText = (payload) => {
const choices = Array.isArray(payload?.choices) ? payload.choices : [];
for (const choice of choices) {
const content = choice?.message?.content;
if (typeof content === "string" && content.trim()) {
return content.trim();
}
// ...
}
// ...
return "";
};

On success the function returns { ok: true, text, id, model }. Every failure path — missing input, a non-2xx status, or an empty reply — returns an object with ok: false rather than throwing, and the outer try/catch converts any unexpected exception into the same shape:

if (!response.ok) {
return {
ok: false,
error: "openrouter_request_failed",
status: response.status,
details: extractErrorMessage(payload, responseText),
};
}

Adapting it for your own agent

To repoint this skeleton at a different service, change a handful of things:

  • ENDPOINT — the URL you POST to.
  • The auth header (and the attribution headers, which are OpenRouter-specific).
  • The request body shape — { model, messages } here; match your provider's schema.
  • extractResponseText — read the field your provider returns the text in.
  • The secret key read from env (and its entry in Required secrets).

Set it up

  1. Copy this integration from the registry — see Registry integrations.
  2. Create the project secret above — see Project secrets.
  3. Preview the agent to confirm it works.