AI workflows, written as intent
Describe the work.
Run the machine.
mashin turns one readable description into an AI workflow you can run. Its goal, model, permissions, approvals, and outputs are defined together.
A complete workflow in one readable document
Meet the email triage machine.
It reads your inbox, classifies each message by urgency, and turns the ones that matter into tasks. Reading email is a call to a Gmail machine; the whole workflow is one readable document.
machine email_triage_to_tasks
achieves
goal "Triage incoming emails into prioritized tasks"
behaves
// Fetch recent emails (calls the Gmail machine)
ask fetch_emails , from: "@mashin/google/gmail/list_messages" max_results: input.limit query: "newer_than:1h"
// Classify each email by urgency, using a fast model
ask classify_emails, using: "fast"
with role "You are an email triage specialist."
returns
classifications as list, is required
// ... create tasks, update cursor, summarize ...
ensures
permissions
allowed to network.httpRead the whole machine (the excerpt elides its reasoning and memory steps)
machine email_triage_to_tasks
achieves
goal "Triage incoming emails into prioritized tasks"
succeeds when "every urgent email creates a task within 5 minutes"
never "miss an email or create duplicate tasks"
for example
assuming last_cursor null
assuming fetch_emails { messages: [{ id: "3", subject: "URGENT: Server down", from: "[email protected]" }, { id: "2", subject: "Weekly newsletter", from: "[email protected]" }, { id: "1", subject: "Build passed", from: "[email protected]" }] }
assuming classify_emails { classifications: [{ email_id: "3", classification: "urgent_actionable" }, { email_id: "2", classification: "noise" }, { email_id: "1", classification: "informational" }] }
assuming create_task_descriptions { tasks: [{ title: "Fix server outage", description: "The production server is down and needs immediate attention.", priority: "high" }] }
assuming save_cursor {stored: true}
given { limit: 10, since: "1h" }
expect { processed: 3, tasks_created: 1, skipped: 2 }
accepts
limit as integer, default: 20
since as string, default: "1h"
responds with
processed as integer
tasks_created as integer
skipped as integer
classifications as list
behaves
// Step 1: Remember where we left off
recall last_cursor key: "last_email_id"
// Step 2: Fetch recent emails (uses Gmail L1 machine)
ask fetch_emails , from: "@mashin/google/gmail/list_messages" max_results: input.limit query: "newer_than:1h"
// Step 3: Filter out already-processed emails
compute filter_new let cursor = steps.last_cursor.value || "" let emails = steps.fetch_emails.messages || [] let new_emails = emails.filter(e => e.id > cursor) { emails: new_emails, count: new_emails.length }
// Step 4: Classify each email
ask classify_emails, using: "fast"
with role "You are an email triage specialist. Classify emails by urgency and actionability."
with task """
For each email, classify as:
- urgent_actionable: needs immediate action (deadline, escalation, blocker)
- actionable: needs action but not urgent (request, follow-up, review)
- informational: FYI only (newsletter, notification, status update)
- noise: can be ignored (spam, marketing, automated)
Return a list of classifications with email_id, subject, classification, and reason.
Emails: ${JSON.stringify(steps.filter_new.emails)}
"""
returns
classifications as list, is required
// Step 5: Create tasks for actionable emails
compute extract_actionable let actionable = steps.classify_emails.classifications.filter(c => c.classification == "urgent_actionable" || c.classification == "actionable" ) { actionable: actionable, count: actionable.length }
// Step 6: Create Linear issues for each actionable email
// (In a real deployment, this would use for_each + call to Linear)
ask create_task_descriptions, using: "fast"
with role "You create concise, actionable task titles and descriptions from emails."
with task """
For each email, create a task with:
- title: short actionable title (verb-first, e.g., 'Review Q4 budget proposal')
- description: 2-3 sentence summary of what needs to be done
- priority: high (urgent_actionable) or medium (actionable)
Emails: ${JSON.stringify(steps.extract_actionable.actionable)}
"""
returns
tasks as list, is required
// Step 7: Update cursor
remember save_cursor operation: "store_structured" key: "last_email_id" value: steps.fetch_emails.messages[0].id
// Step 8: Compute summary
compute summarize let total = steps.filter_new.count let created = steps.extract_actionable.count let skipped = total - created { processed: total, tasks_created: created, skipped: skipped, classifications: steps.classify_emails.classifications }
ensures
permissions
allowed to network.http, network.http
verifies
test "classifies emails correctly"
assuming last_cursor null
assuming fetch_emails { messages: [{ id: "1", subject: "URGENT: Server down", from: "[email protected]" }] }
assuming classify_emails { classifications: [{ email_id: "1", classification: "urgent_actionable" }] }
assuming create_task_descriptions { tasks: [{ title: "Fix server outage", description: "Server is down", priority: "high" }] }
assuming save_cursor {stored: true}
given { limit: 10 }
expect { processed: 1 }
test "skips already processed emails"
assuming last_cursor { value: "5" }
assuming fetch_emails { messages: [{ id: "3", subject: "Old" }] }
assuming classify_emails { classifications: [] }
assuming create_task_descriptions { tasks: [] }
assuming save_cursor {stored: true}
given { limit: 10 }
expect { processed: 0 }Effects are calls.
Reading email is ask ... from: "@mashin/google/gmail/list_messages". Effects happen by calling governed machines.
The grant is the kernel primitive.
allowed to network.http: every effect reduces to a small, closed set of I/O primitives you can see.
The model is a tier.
using: "fast" names a tier, not a vendor. Swap it without touching the workflow.
The document is the workflow.
In a typical AI application, intent is spread across prompts, orchestration code, permission checks, and audit tools. A mashin machine keeps those decisions together in a document people can read and the runtime can execute. There is no second implementation of the workflow to build or maintain.
| Typical AI workflow | A mashin machine |
|---|---|
| Behavior spread across the stack | Intended behavior declared together |
| Permissions implemented separately | Permissions visible in the machine |
| Model changes can require rework | Model choice is explicit and replaceable |
| Audit added around the workflow | Each run produces a record |
Bound before it acts. Recorded after it runs.
See what a machine may do,
then verify what it did.
Every machine declares its permissions and approval points. When it runs, mashin checks each action against those boundaries first, and writes a receipt after: every entry cryptographically linked to the one before, so edits and gaps show, and verification runs in your own browser.
Declared permissions
See which tools and data the machine may use. An undeclared action is refused, and the refusal names its reason.
Human approval
Consequential actions pause until a person approves them. The answer is part of the record.
Run receipts
Inspect the steps, decisions, and outputs of each run. Replay it. Verify the record yourself.
Write it once. Run it where the work happens.
The same machine can run on a schedule, through an API, from a shortcut, as an MCP tool, in the cloud, or on your own computer.
One definition, multiple ways to run it, with the same rules and records.
Less plumbing. More legible software.
Build the behavior once
Define the goal, reasoning steps, boundaries, and outputs together instead of scattering them across orchestration code.
Change models without changing the workflow
Choose the model for each reasoning step and replace it without redesigning the machine.
Know what happened
Every run leaves a receipt that makes the machine's actions and results inspectable, by you and by anyone you answer to.
Soon: watch the email triage machine run here, and read its receipt.
Build your first machine at launch.
Get launch access and occasional research notes.
No spam. The launch announcement and occasional research notes.
Check your email to confirm.
We sent a confirmation link to your inbox. Click it to secure your spot.
That didn't go through.
Please try again, or email [email protected] directly.
mashin exists to enable the intelligence economy: intelligent systems trustworthy by construction rather than by human effort.The mashin Way