Skip to main content

What you will have

A roster agent called Underwriting Agent. When an application ticket is assigned to it in Linear, it pulls the Middesk result, the registry and ownership records, and the application answers from a read-only database, checks each provider flag against the underwriting policy in Notion, and writes a decision memo in which every flag is either resolved with a source or listed as open. If a document is missing it drafts the request. Every Monday it re-reviews merchants due for a periodic check and posts the summary to Slack. It cannot change an application’s status, write to the database, or send anything to a merchant; those wait for an underwriter. This page follows the six steps of Build an agent. The Build pages explain each step; this page gives the concrete values for this one agent.

The agent spec

1. Define the job

Read Define the job first. The objective needs an input, an output and a boundary; underwriting has an unusually sharp boundary, so write it down before anything else.
1

Create the roster agent

Open Agents and click New Agent. On Profile, name it Underwriting Agent. On Instructions, use this description:
Given a pending merchant application, compares the KYB provider result, the business registry, beneficial ownership and the application answers, and writes a decision memo where every flag is resolved with a source or listed as open, plus a draft document request. Never changes an application’s status.
And these system instructions:
Skip Triggers for now and click Create agent.
2

Point it at a template

Open the agent’s card. Under Default template pick Underwriting (create it in step 3 if it does not exist yet) and leave Coding agent on Claude Code. Click Save profile.

2. Measure success

Read Measure success. Underwriting has three kinds of run and a grader can only judge one category at a time, so give it three.
Performance evaluation section of the agent sheet with a category expanded

Three categories, each with a when-to-use, a success criterion and the human cost that prices the scorecard.

1

Add the three categories

In the agent sheet, scroll to Performance evaluation and click Add evaluation category three times.Add a grading tag risk_tier on every category with the instruction “low, medium or high, taken from the memo’s recommendation line”. Set Avg human cost (USD) to 90 and Avg human time (minutes) to 75.
2

Set the monthly budget

Set Monthly budget to 800. This flags the agent on the scorecard and writes an audit event when spend passes the cap. It does not stop runs; use org limits under Guardrails > Limits for a hard cap.
rubric.json for the CLI:

3. Give it tools

Read Give it tools. None of the KYB vendors is a built-in provider, so Middesk is a custom provider here; Persona or Alloy would be set up the same way with their own fields. Postgres is also custom. Notion is built in.
Dialog asking what to add, with Tool and MCP server options

Tools and MCP servers are added from the same chooser. Middesk and Postgres are custom tool providers; Notion comes from the catalog.

1

Create the Underwriting template

Go to Templates, click New Template, choose Blank environment, name it Underwriting, and click Create Template. Nothing is cloned; the template exists to carry connections, the skill and later the guardrails.
2

Define Middesk as a custom provider

In Settings > Context > Tools & MCP, click New tool or MCP server, choose Tool, and define a custom provider with one static auth method. The secret lands in MIDDESK_API_KEY; an optional base URL lets you point the sandbox at Middesk’s sandbox environment while proving.
3

Connect Middesk at agent scope

Connect the new provider and choose the agent scope, picking Underwriting Agent. An agent-scoped connection is used only by this agent’s runs, so Middesk usage is attributed to the agent, and it reaches the agent’s sessions without any skill having to require it. The CLI creates only org and personal connections, so this one is done in the dashboard. See the credential hierarchy.
4

Define and connect Postgres read-only

Create a second custom provider, postgres, with one static field connection_string (kind secret) materialized to POSTGRES_CONNECTION_STRING. Connect it at org scope with a role that can only SELECT from the applications, owners and documents views. Nothing in Runtime downgrades a credential, so the read-only guarantee has to come from the database role.
5

Connect Notion from the catalog

Click New tool or MCP server, choose Tool, pick Notion from Add a provider, and connect it at org scope with an internal integration token that has read access to the Underwriting Policy pages. The skill cites these pages by URL.
Org and personal connections reach a session only when an attached skill lists the provider in requires.integrations. The skill in the next step names middesk, postgres and notion, so Postgres and Notion arrive through the skill and Middesk arrives both ways.

4. Define how it works

Read Define how it works. The runbook is a skill, the prohibitions live in the instructions and the skill for now, and the triggers are Linear plus a schedule. Guardrails wait until step 6.
1

Write the underwriting-memo skill

The skill has three files. SKILL.md is the procedure:
references/memo-template.md, excerpt:
references/flag-glossary.md maps each Middesk task key (for example tin, address_verification, sos_active, watchlist) to what it means and which policy section governs it.Create the skill, upload the two reference files, and declare the providers it requires.
2

Attach the skill and build the template

Attach underwriting-memo to the Underwriting template and build once. Anything attached after this build is not in the snapshot until the next one.
3

Connect Linear for new applications

In the agent sheet, under Triggers, click Connect on the Linear row. The OAuth flow finishes in the browser. In the Linear tab, keep Default template on Underwriting, and under Team overrides route the Underwriting Linear team to this template so that other teams’ assignments do not launch it. Assigning a ticket to the agent, or mentioning it, launches a run; the memo comes back as agent activities and a comment on the issue.
New Agent dialog, Triggers step listing Slack, Linear, GitHub, Email, WhatsApp and SMS

Triggers connect from the agent sheet. Linear finishes in the browser; Email is one click.

If your team does not use Linear, click Create inbox on the Email row instead and have the application system forward new applications to the agent’s address. The reply comes back in the same email thread.
4

Schedule the periodic reviews

Open Agents > Scheduled and click New scheduled agent. Name it Periodic merchant reviews, run it as the Underwriting Agent roster agent so the run is graded under periodic-review and receives the agent-scoped Middesk key, and use this prompt:
Run the periodic review for every merchant whose next_review_at is before today. One memo per merchant using the underwriting-memo skill. End with a summary table: merchant, risk tier, what changed.
Schedule it weekly on Monday at 13:00 UTC and post to the #underwriting Slack channel. Cron is five fields in UTC with no time zone, so 13:00 UTC is 06:00 in San Francisco in summer and 05:00 in winter. Create it disabled; you enable it in step 5 after a Run now.

5. Prove it works

Read Prove it works and iterate. No guardrail exists yet on purpose. The agent is safe by scope: the database role is read-only, Middesk is called with a key you can point at its sandbox environment, the sandbox is destroyed after each run, and the Linear team is a test team or the schedule is disabled.
1

Seed five applications

Put five applications with known outcomes in the database (a staging copy is fine) and write down the expected memo before running anything.Also include one case you expect to fail the grade, such as a ticket that names an application id that does not exist, so you see what a failure looks like.
2

Run the Linear cases

Assign the first three tickets to the agent in the test Linear team. Each launches a session. Watch it under Sessions or Agents > Runs. When a run reaches the memo_attach approval, the session card shows Approve and Reject; approve to let it finish so it can be graded.
Sessions grid with a run showing its approval outcome

A run waiting on an approval shows it on the session card; approve to let the run finish and be graded.

3

Run the schedule once by hand

On Agents > Scheduled, use Run now on Periodic merchant reviews. It executes the identical code path a Monday tick takes, so a misconfigured schedule fails in front of you instead of silently at 13:00 UTC. Read the summary in #underwriting.
4

Read the grades and the scorecard

A few minutes after each run finishes, read its grade. Then open Activity > Agents and pick Underwriting Agent: six graded runs, the hit rate, and value returned at $90 per success.
5

Tighten one thing, re-run, then enable the schedule

A memo that missed the third officer gets a step in the skill. A grader that passed a memo without sources gets a stricter success_criteria. A run that could not read documents gets the view added to the role. Change one thing, re-run the affected case, and only when all five pass enable the schedule.While the cases run, write down every command pattern and host the agent used. That list is the input to step 6.

6. Add guardrails and approvals

Read Add guardrails and approvals. Only now, with five passing cases, do you know what the agent runs. Add one rule at a time and re-run a seeded case after each.
1

Deny writes to the application tables

Under Settings > Guardrails > Allowlists, create deny rules for anything that writes through psql, then attach them to the Underwriting template.
2

Deny Middesk writes, except the one the runbook needs

Creating a Middesk business is a POST to /v1/businesses. Ordering extra verifications is a POST under /v1/businesses/<id>/. Deny beats allow whenever both match, so the deny pattern itself has to leave out any path you intend to keep.If onboarding already created the Middesk business and the runbook only reads, deny every POST:If the runbook must create the business itself, deny only writes below an existing business plus every PATCH and DELETE. The create call matches no deny rule and falls through to the allow rule, so it needs no rule of its own:
3

Set the default policy to ask

On the Allowlists tab set the default policy to ask, so any command outside the patterns above pauses for a permission decision instead of running. The CLI does not set this; use the tab or PUT /api/cloud/organizations/<org_id>/allowlist-policy with {"default_policy": "ask"}.
4

Pin the network

As soon as one network rule exists, egress is deny-all plus the list. This agent needs five hosts.
5

Rebuild and re-run a case

Allowlist rules are materialized into the snapshot; network rules apply at session creation. Rebuild, then re-run the clean approval and the missing-document cases. If one now stalls, the last rule you added is the cause.
6

Keep both approval gates in the runbook

The skill already requests two approvals: memo_attach before the memo is posted to the ticket, and document_request before any request goes to the merchant. Both use --required-team <underwriting_team_id> so only underwriters can resolve them; admins and owners always can. Approvals are resolved on the session card or with the CLI, not in Slack or Linear.

What stays human

  • The decision. The memo ends in a recommendation; an underwriter approves, declines or conditions the application in the application system. The agent has no path to that status field: the database role cannot write, and the deny rules refuse the attempt.
  • Anything sent to the merchant. The agent drafts the document request; a person sends it after the document_request approval.
  • Ordering new verifications. Unless you deliberately allow the single create-business path, the agent reads what onboarding already ordered.
  • Changing the rubric. When the grader disagrees with an underwriter, the underwriter edits the success criteria, not the agent.

Gotchas

  • Middesk is not built in. It is a custom provider you define; the JSON above is the whole definition. Persona and Alloy are set up the same way with their own field names and base URLs.
  • The agent-scoped Middesk key applies only to this agent’s runs. A session someone opens from the Underwriting template by hand does not receive it, and falls to a personal or org-wide Middesk connection if one exists, otherwise middesk shows as an unmet requirement.
  • Postgres and Notion arrive through the skill. If requires.integrations on underwriting-memo does not list postgres and notion, those org-wide connections are silently left out of the session.
  • Attached is not built. After attaching the skill or a rule, template get shows attachments_changed_since_build: true until you build again.
  • Schedules run in UTC. 0 13 * * 1 is Monday 13:00 UTC all year; local time shifts with daylight saving.
  • A periodic run with no post target is silent. Set the Slack channel on the schedule or the summary is only visible under Sessions.
  • Deny beats allow. A deny pattern such as curl*-X POST*api.middesk.com* also matches the create-business call, and no allow rule can rescue it. If the runbook creates the business, narrow the deny to api.middesk.com/v1/businesses/* so the create path never matches a deny rule.
  • Approvals with nobody watching wait forever. Scope --required-team to the team that is on rotation, and give the runbook a wait --timeout so a run fails cleanly at end of day instead of idling.

Payment support agent

A ticket-driven agent that reconstructs a charge and drafts the reply.

Fraud and risk review agent

A scheduled agent that assembles review packets from Stripe and the warehouse.

Build an agent

The six steps this example follows.