Your first tool, end to end
Build post_status, a tool that opens an incident on a status page. Requires the daemon
installed, Node 22.18+, and a
Statuspage page ID and API key.
1. Start an app
Section titled “1. Start an app”mkdir statuspage && cd statuspagenpm init -y && npm pkg set type=module2. Write the tool
Section titled “2. Write the tool”import { Wardrik } from "@wardrik/sdk";import { z } from "zod";
const page = process.env.STATUSPAGE_PAGE_ID;const key = process.env.STATUSPAGE_API_KEY;
const wardrik = new Wardrik({ name: "statuspage" });
wardrik.tool({ name: "post_status", description: "Open an incident on the public status page, with its first update.", input: z.object({ name: z.string().describe("The incident's title, as customers see it"), status: z.enum(["investigating", "identified", "monitoring", "resolved"]), body: z.string().describe("The first update, in plain words"), }), run: async (incident, { signal }) => { const response = await fetch(`https://api.statuspage.io/v1/pages/${page}/incidents`, { method: "POST", headers: { authorization: `OAuth ${key}`, "content-type": "application/json" }, body: JSON.stringify({ incident }), signal, }); if (!response.ok) throw new Error(`Statuspage answered ${response.status}`);
const { id, shortlink } = await response.json(); return { id, shortlink }; },});
const stop = new AbortController();process.on("SIGTERM", () => stop.abort());process.on("SIGINT", () => stop.abort());
await wardrik.work({ signal: stop.signal });- It isn't
readOnly, so every call needs approval unless a policy allows it. - A thrown error fails the call. The model receives the error message.
3. Connect it
Section titled “3. Connect it”Allow the user default/@statuspage to serve tools to the org's agents:
roles: tools: {rules: [{verbs: [serve], kinds: [agent]}]}bindings: - {org: default, role: tools, subjects: [user:default/@statuspage]}systemctl --user restart wardrikwardrik token create statuspage --subject user:default/@statuspageexport STATUSPAGE_PAGE_ID=... STATUSPAGE_API_KEY=...WARDRIK_TOKEN=wdk_... node statuspage.tsdefault is the org in config.yaml. The app opens no port, and the Statuspage key stays in
the app.
4. Give an agent the tool
Section titled “4. Give an agent the tool”---description: Posts to the public status page when asked.tools: [workers/*]policy: ask: workers/post_status: This posts publicly on the status page.---You post incidents on the public status page. Write for customers, in plain words.5. Try it
Section titled “5. Try it”wardrik reloadwardrik ask status "Checkout is failing for some customers. Post that we're investigating."wardrik approval lsAGENT CALL TOOL WHYstatus call_7c2e… workers__post_status This posts publicly on the status page.wardrik approval approve status call_7c2e…wardrik approval deny status call_7c2e… --reason "We don't post until it's confirmed."On approval, your app posts the incident and the agent receives the link.
6. Run it as a service
Section titled “6. Run it as a service”[Unit]Description=Status page tools for WardrikAfter=wardrik.service
[Service]WorkingDirectory=%h/statuspageEnvironmentFile=%h/.config/statuspage.envExecStart=/usr/bin/node statuspage.tsRestart=on-failure
[Install]WantedBy=default.targetchmod 600 ~/.config/statuspage.env # WARDRIK_TOKEN and the Statuspage keyssystemctl --user daemon-reloadsystemctl --user enable --now statuspageFor other machines or containers, see Host your tools.