Skip to main content

LangGraph Hosted Assistant Agent

This integration calls a hosted LangGraph assistant with your input and returns the latest assistant reply, so you can evaluate a LangGraph deployment.

Required secrets

SecretWhat it is
ASSISTANT_IDHosted assistant identifier.
X_API_KEYAPI key for the LangGraph deployment.
ENDPOINT_URLEndpoint URL for the LangGraph deployment's API.

Where to get the credentials

In your LangGraph deployment, copy the assistant id for ASSISTANT_ID, the deployment's API key for X_API_KEY, and the deployment's API endpoint URL for ENDPOINT_URL. Store all three as project secrets.

Turn support

Single-turn. Each evaluation case is sent as an independent request.

Limitations and notes

  • All three secrets must point at the same deployment.
  • Throughput and availability follow your own LangGraph deployment's limits.

How the agent works

The integration you copy is a single JavaScript function. This walkthrough follows the real code so you can adapt the same pattern to connect a custom agent to your own service.

The entry point is an exported process function. Its input is the evaluation case text the platform sends in.

export async function process(input) {
try {
const assistantId = String(env.ASSISTANT_ID ?? "").trim();
const apiKey = String(env.X_API_KEY ?? "").trim();
const endpointUrl = String(env.ENDPOINT_URL ?? "").trim();
const { text } = parseInput(input);

Secrets are read straight off the global env object by name — the same keys listed in Required secrets above. Input is normalized first: parseInput accepts either a JSON object (picking text, prompt, or input) or a plain string, always returning { text }.

const parseInput = (input) => {
const raw = String(input ?? "").trim();
if (!raw) {
return { text: "" };
}

try {
const parsed = JSON.parse(raw);
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
return {
text: String(parsed.text ?? parsed.prompt ?? parsed.input ?? "").trim(),
};
}
} catch {}

return { text: raw };
};

If any secret or the text is missing, it fails fast by returning { ok: false, error: "missing_required_input" }.

The request is a POST with a JSON body and an x-api-key header. Because hosted LangGraph deployments accept different input shapes, the agent builds several candidate bodies and tries each one until a request succeeds.

const buildBodies = (assistantId, text) => [
{
assistant_id: assistantId,
input: {
messages: [{ role: "user", content: text }],
},
},
{
assistant_id: assistantId,
input: { text },
},
{
assistant_id: assistantId,
input: text,
},
];

const executeRequest = async (url, apiKey, body) => {
const response = await fetch(url, {
method: "POST",
headers: {
"content-type": "application/json",
"x-api-key": apiKey,
},
body: JSON.stringify(body),
});
// ...
};

The reply is pulled from the response by walking the payload for messages and returning the text of the last assistant/ai message, falling back to output_text, text, or output string fields.

const extractReplyText = (payload) => {
const messages = collectMessages(payload);

for (let index = messages.length - 1; index >= 0; index -= 1) {
const message = messages[index];
const role = String(message?.role ?? message?.type ?? "").toLowerCase();
if (role === "assistant" || role === "ai") {
const text = extractContentText(message.content ?? message.text);
if (text) {
return text;
}
}
}

for (const key of ["output_text", "text", "output"]) {
if (typeof payload?.[key] === "string" && payload[key].trim()) {
return payload[key].trim();
}
}

return "";
};

The loop returns { ok: true, text, status } on the first body that both succeeds and yields a reply. If every attempt fails it returns { ok: false, error: "langgraph_request_failed", details }, and any thrown error is caught and returned as { ok: false, error }. The convention is to always return an object rather than throw.

for (const body of buildBodies(assistantId, text)) {
const result = await executeRequest(endpointUrl, apiKey, body);
const replyText = extractReplyText(result.body);

if (result.ok && replyText) {
return { ok: true, text: replyText, status: result.status };
}
// ... record lastFailure
}

Adapting it for your own agent

To point this skeleton at a different service, change:

  • The endpoint URL the request is sent to (here, the ENDPOINT_URL secret).
  • The auth header (here, x-api-key).
  • The request body shape — drop the multi-body fallback if your service accepts a single known format.
  • The response field your reply is read from in extractReplyText.
  • The secret keys you declare and read off env.

Set it up

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