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
| Secret | What it is |
|---|---|
ASSISTANT_ID | Hosted assistant identifier. |
X_API_KEY | API key for the LangGraph deployment. |
ENDPOINT_URL | Endpoint 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_URLsecret). - 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
- Copy this integration from the registry — see Registry integrations.
- Create the project secrets above — see Project secrets.
- Preview the agent to confirm it works.