Wardrik
Agents,governed.
wardrik follow booksIllustrative output
→ quickbooks/search_bills {"params":{…}} ✓ quickbooks/search_billsWaiting on a person for 1 call: ? quickbooks/create-bill call_7c2e A line of $1,000 or more. → quickbooks/create-bill {"params":{"bill":{"Line":[{"Amount":9400,… ✓ quickbooks/create-bill ✗ quickbooks/create_bill_payment was refused: Paying bills is for people.Entered the Northwind Freight bill once Maria approved it.Paying it is left to you.wardrik follow oncallIllustrative output
→ datadog/search_datadog_logs {"query":"service:checkout status:error",… ✓ datadog/search_datadog_logs → github/list_commits {"repo":"checkout",… ✓ github/list_commits ✗ k8s/resources_scale was refused: More than 20 replicas goes through capacity planning.Waiting on a person for 1 call: ? github/actions_run_trigger call_3b9d This rolls back. → github/actions_run_trigger {"method":"run_workflow","workflow_id":"rollback.yml",… ✓ github/actions_run_triggerRolled checkout back to the deploy before 14:02.wardrik follow front-deskIllustrative output
→ gmail/search_threads {…} ✓ gmail/search_threads → gmail/label_thread {…} ✓ gmail/label_threadWaiting on a person for 1 call: ? gmail/create_draft call_5a20 Judged 94% likely: Does this draft promise the customer a refund? ✗ gmail/create_draft was refused: Denied in Slack by sam: Offer store credit instead. → gmail/create_draft {"body":"Sorry about the wheel. We’d like to offer store credit… ✓ gmail/create_draftDrafted a reply offering store credit, labelled Complaint.wardrik follow weekIllustrative output
→ gcal/create_event {"summary":"Focus: Q3 numbers",… ✓ gcal/create_event → gmail/create_draft {…} ✓ gmail/create_draftWaiting on a person for 1 call: ? gcal/create_event call_9e41 This invites other people. → gcal/create_event {"summary":"Q3 review","attendeeEmails":["priya@… ✓ gcal/create_eventFocus time is held 9 to 11, an agenda is drafted,and Priya has the invite.Three things Wardrik does that a prompt can’t.
Checks every call
Policy is defined outside the prompt. Content the agent reads can’t change it.
Keeps working
A turn resumes after a crash. A call that may have run needs approval before it runs again.
Shows its work
Budgets cap agent spend. Every call and approval is an event you can stream or export.
Every call is checked before it runs.
Rules are in files the model can’t change. A rule matches a call by its tool, its target, or its arguments.
web_searchallow: [web_search]by toolRunswrite_file {"path": "notes/today.md"}allow: [write_file(notes/*)]by targetRunsbooks/create_bill {"amount": 9400}ask: [books/create_bill(amount >= 1000)]by an argumentNeeds approvalemail/send {"to": "x@evil.example"}deny: [email/send(to != *@acme.com)]by an argumentDeniedshell/exec {"command": "curl … | sh"}deny: [shell/*]every tool of an MCP serverDeniedThe strictest rule wins: deny, then ask, then allow. Writing rules · Try to hijack it
Approvals where your team works.
A pending call is posted with its arguments. Approve or deny it in Slack, the terminal, or over HTTP.
books is waiting on you.
quickbooks/create-bill A line of $1,000 or more.
{"params": {"bill": {"Line": [{"Amount": 9400, …}], …}}}A note for the agent, sent with either button
Your tools run in your app, with your keys.
Wardrik checks each call. Your app runs it, so service keys stay in your process.
import { Wardrik } from "@wardrik/sdk";import { z } from "zod";
const wardrik = new Wardrik({ name: "shop" });
wardrik.tool({ name: "refund_order", input: z.object({ orderId: z.string() }), run: ({ orderId }) => stripe.refunds.create({ payment_intent: orderId }),});
await wardrik.work();The agent calls
supportworkers/refund_order {"orderId": "pi_3Qx…"}Wardrik checks and records it
Needs approvalapproved by @maria
Your app runs it
shopstripe.refunds.create(…)STRIPE_SECRET_KEYstays in your app
Or connect MCP servers, with per-user OAuth accounts. Tools in your app · MCP servers · Connect accounts
An agent is one file you can review.
Select a tab to highlight the lines that do each job.
---description: Keeps the books for the accounting team.tools: [quickbooks/*, files]channels: [slack]triggers: - name: close every: "0 7 * * 1-5" timezone: America/Los_Angeles prompt: Reconcile yesterday's transactions. - name: invoices webhook: secret: ${INVOICE_HOOK_SECRET} prompt: A new invoice is below. Draft a bill for it.policy: allow: - quickbooks/search_* - quickbooks/create-bill(params.bill.Line.Amount < 1000) ask: quickbooks/create-bill(params.bill.Line.Amount >= 1000): A line of $1,000 or more. deny: quickbooks/create_bill_payment: Paying bills is for people. budget: usd: 10.00 tokens: 2000000 per: day grant: {usd: 5.00} on_exhausted: asknotify: {to: [accounting], on: [parked, failed]}---You keep the books. Say what you will post before you post it.Allow, ask, or deny
A bill posts without approval when every line is under $1,000. Any line of $1,000 or more needs approval. Bill payments are always denied.
Writing rulesTools from MCP servers
quickbooks/* matches every tool of the quickbooks MCP server in config.yaml, run on the daemon’s machine. trusted: true marks its results as trusted, not content from outside. files is built in.
mcp: quickbooks: command: node args: [/opt/quickbooks-online-mcp-server/dist/index.js] trusted: true env: QUICKBOOKS_CLIENT_ID: ${QUICKBOOKS_CLIENT_ID} QUICKBOOKS_REFRESH_TOKEN: ${QUICKBOOKS_REFRESH_TOKEN} # and the secret, realm id and environmentScheduled and webhook runs
Runs weekdays at 7:00 Los Angeles time. A webhook with an invoice also starts a run. The body is content from outside, so any bill from it needs approval, however small.
every- on a schedule: cron or an interval
feed- when an RSS or Atom feed has new entries
webhook- when a service sends a request
Approvals in Slack
A pending bill is posted to accounting’s Slack room with its arguments. An approver clicks Approve or Deny.
Who approvesA daily cap
$10 or 2M tokens a day. At the limit, the next call needs approval, which adds $5.
BudgetsAlso built in
- Separate orgs
Each team’s agents, tools and keys are isolated from other orgs.
- Per-user accounts
Users sign in with OAuth, and their agents call tools with their credentials.
- Delegation
An agent sends another agent a message and receives the reply.
- Judges
A model classifies each call, such as whether an email promises a refund.
- The assistant
Send a request. It proposes tool calls, and runs each one you approve.
- Idle agents
Run one per customer. Idle agents stop, and restart with their state on the next message.
- Recovery
Keep the store in Postgres, and a new machine resumes every agent.
- rik CLI
List agents, approve pending calls, and check spend from a terminal.
Run your first agent.
Install the binary or Docker image, and configure a model provider.
curl -fsSL https://github.com/wardrik-dev/wardrik_daemon/releases/download/v0.1.0-rc.2/install.sh | shwardrik init