Integrations

The cleanest way to integrate Chidori with external systems is as an event-driven agent: one file, one agent(event, chidori) function, one HTTP port. Every external system that can POST JSON becomes a source of events.

The pattern

chidori serve agents/integrations.ts --port 8080
import type { Chidori } from "chidori";

export async function agent(event, chidori: Chidori) {
  if (event.path === "/github") return handleGithub(event, chidori);
  if (event.path === "/slack") return handleSlack(event, chidori);
  if (event.path === "/alert") return handleAlert(event, chidori);

  return { status: 404, body: { error: "Unknown path: " + event.path } };
}

Then point each external system at the matching URL — one agent, many integrations.

GitHub webhooks

GitHub sends a JSON body and a x-github-event header identifying the event type.

async function handleGithub(event, chidori: Chidori) {
  const ghEvent = event.headers["x-github-event"] ?? "";
  const body = event.body;

  if (ghEvent === "pull_request" && body.action === "opened") {
    return reviewPr(body.pull_request, chidori);
  }

  if (ghEvent === "issues" && body.action === "opened") {
    return triageIssue(body.issue, chidori);
  }

  return { status: 200, body: { ignored: ghEvent } };
}

async function reviewPr(pr, chidori: Chidori) {
  const diff = await chidori.http(pr.diff_url, {
    headers: { Accept: "application/vnd.github.v3.diff" },
  });
  const review = await chidori.prompt(
    "Review this pull request. Flag correctness, security, and style issues.\n\n" +
      "Title: " + pr.title + "\n\nDiff:\n" + diff.body,
    { maxTokens: 1000 },
  );

  await chidori.http(pr.comments_url, {
    method: "POST",
    headers: { Authorization: "Bearer " + chidori.env("GITHUB_TOKEN") },
    body: { body: review },
  });
  return { status: 200, body: { reviewed: pr.number } };
}

async function triageIssue(issue, chidori: Chidori) {
  const classification = await chidori.prompt(
    "Classify this issue as 'bug', 'feature', 'question', or 'duplicate'. " +
      "Respond with just the word.\n\nTitle: " + issue.title +
      "\n\nBody:\n" + (issue.body ?? ""),
    { maxTokens: 20 },
  );
  await chidori.http(issue.url + "/labels", {
    method: "POST",
    headers: { Authorization: "Bearer " + chidori.env("GITHUB_TOKEN") },
    body: { labels: [classification.trim().toLowerCase()] },
  });
  return { status: 200, body: { triaged: issue.number, label: classification } };
}

Register the webhook in GitHub under Settings → Webhooks, pointing at https://your-host/github.

Slack slash commands

Slack POSTs a form-encoded body; Chidori parses it into event.body as an object:

async function handleSlack(event, chidori: Chidori) {
  const body = event.body;
  const command = body.command ?? "";
  const text = body.text ?? "";

  if (command === "/summarize") {
    return summarizeThread(body.channel_id, body.thread_ts, chidori);
  }

  if (command === "/explain") {
    return { status: 200, body: { text: await chidori.prompt("Explain like I'm 5:\n" + text) } };
  }

  return { status: 200, body: { text: "Unknown command: " + command } };
}

Alert responders

Chidori is a natural fit for on-call copilots — an alert comes in, the agent fetches related metrics, proposes a diagnosis, and pages a human only if it can't self-resolve.

async function handleAlert(event, chidori: Chidori) {
  const alert = event.body;
  const severity = alert.severity ?? "unknown";
  const service = alert.service ?? "unknown";

  // Pull related metrics and recent deploys in parallel
  const context = await chidori.parallel([
    () => chidori.tool("prometheus_query", { query: `rate(errors{service="${service}"}[5m])` }),
    () => chidori.tool("recent_deploys", { service, hours: 2 }),
    () => chidori.tool("recent_alerts", { service, hours: 6 }),
  ]);

  const diagnosis = await chidori.prompt(
    await chidori.template("prompts/alert.jinja", {
      alert,
      metrics: context[0],
      deploys: context[1],
      related: context[2],
    }),
    { maxTokens: 500 },
  );

  if (severity === "critical") {
    await chidori.tool("page_oncall", { service, diagnosis });
  }

  return { status: 200, body: { diagnosis, severity } };
}

Secrets

Never inline secrets. Read them with chidori.env() and pass them through to chidori.http():

await chidori.http("https://api.example.com/...", {
  method: "POST",
  headers: { Authorization: "Bearer " + chidori.env("API_TOKEN") },
  body: payload,
});

Debugging failed integrations

Because every integration run is a session under chidori serve, any production failure is a replayable checkpoint. Grab the checkpoint, run it locally, edit the offending call's cached result in the debugger to branch the history, and iterate — zero additional LLM spend.

Was this page helpful?