コンテンツにスキップ
Developer Preview — APIs and language features may change before 1.0

Lesson 4: Taking Action

このコンテンツはまだ日本語訳がありません。

Your machine classifies emails and routes them. But “routed_to: notify_team” is just a label. Nobody actually gets notified. A task saying “create_task” does not create a task anywhere.

This lesson connects your machine to real systems: Microsoft Teams for notifications, Planner for tasks.

You have seen ask classify, using: "claude-haiku-4" which asks an AI to reason. There is another kind of ask:

ask notify, from: "@mashin/actions/microsoft/graph/send_teams_message"
team_id: "ops-team"
channel_id: "ops-alerts"
message_body: "Urgent email from " + input.sender + ": " + input.subject

ask...from: produces an intent to call another machine. The runtime mediates this intent (checking that your machine has permission to send Teams messages) before executing it. @mashin/actions/microsoft/graph/send_teams_message is a built-in action machine that handles the API call, authentication, retries, and error handling.

The three field names are not yours to choose. They are that machine’s accepts contract, exactly like the one you wrote in Lesson 2: it accepts team_id, channel_id, and message_body, and responds with message_id, created_at, success, and status_code.

You do not write HTTP requests. You do not manage tokens. You express intent; the runtime handles execution.

Here is the classifier with real actions:

machine email_triage
accepts
subject as text, is required
sender as text, is required
body as text
responds with
routed_to as text
action_taken as text
behaves
ask classify, using: "anthropic:claude-haiku-4"
with task "Classify this email.\n\nFrom: ${input.sender}\nSubject: ${input.subject}\nBody: ${input.body}"
returns
priority as text, is required, choices: ["urgent", "today", "later", "ignore"]
confidence as number, is required, range: 0.0..1.0
action as text, is required
reason as text
decide route
when classify.confidence < 0.7
run flag_for_human
when classify.priority == "urgent"
run notify_team
when classify.action == "create_task"
run create_planner_task
otherwise
{routed_to: "inbox", action_taken: "none"}
flows
flow notify_team
ask send_alert, from: "@mashin/actions/microsoft/graph/send_teams_message"
team_id: "ops-team"
channel_id: "ops-alerts"
message_body: "Urgent: " + input.subject + " from " + input.sender + "\n" + classify.reason
compute done
{routed_to: "notify_team", action_taken: "Teams message sent to ops-alerts"}
flow create_planner_task
ask create_task, from: "@mashin/actions/microsoft/graph/create_planner_task"
plan_id: "email-triage"
title: input.subject
description: input.body
compute done
{routed_to: "create_task", action_taken: "Planner task created: " + create_task.task_id}
flow flag_for_human
ask send_review, from: "@mashin/actions/microsoft/graph/send_teams_message"
team_id: "ops-team"
channel_id: "email-review"
message_body: "Needs review (confidence: " + classify.confidence + "): " + input.subject + " from " + input.sender
compute done
{routed_to: "human_review", action_taken: "Flagged in email-review"}
verifies
test "routes urgent email to the team"
assuming classify {priority: "urgent", confidence: 0.95, action: "notify", reason: "Client escalation"}
assuming send_alert {message_id: "1629454149", created_at: "2026-04-01T10:30:45Z", success: true, status_code: 201}
given {subject: "URGENT: Client unhappy", sender: "[email protected]", body: "Call me"}
expect {routed_to: "notify_team", action_taken: "Teams message sent to ops-alerts"}
test "creates a task for actionable email"
assuming classify {priority: "today", confidence: 0.9, action: "create_task", reason: "Review request"}
assuming create_task {task_id: "task-123", title: "Can you review this document?", plan_id: "email-triage", status: 201}
given {subject: "Can you review this document?", sender: "[email protected]", body: "Attached"}
expect {routed_to: "create_task", action_taken: "Planner task created: task-123"}
test "flags low-confidence email for a human"
assuming classify {priority: "today", confidence: 0.5, action: "notify", reason: "Unclear"}
assuming send_review {message_id: "1629454150", created_at: "2026-04-01T10:31:02Z", success: true, status_code: 201}
given {subject: "Hmm", sender: "[email protected]", body: "?"}
expect {routed_to: "human_review", action_taken: "Flagged in email-review"}

ask...from: calls a built-in action machine. Three different ones:

  • @mashin/actions/microsoft/graph/send_teams_message sends a Teams message
  • @mashin/actions/microsoft/graph/create_planner_task creates a Planner task
  • Both handle authentication, retries, and error handling automatically

flows organize related steps. flow notify_team contains the steps that run when an email is urgent. flow create_planner_task handles the task creation path. The decide step uses run flow(name) to jump to the right flow.

You will learn more about flows in the next lesson. For now, think of them as named groups of steps.

Notice something: this machine now sends messages and creates tasks. Those are real actions with real consequences. mashin tracks every one:

  • The execution trace shows which action machines were called, with what arguments
  • The governance record logs every external action
  • If Teams is down, the error is captured with the full context

You did not add this tracking. It is automatic. Every ask from: call goes through the governed execution pipeline.

The standard library has action machines for common systems:

Category Examples
Microsoft Teams messages, Planner tasks, Outlook email
Google Gmail, Calendar, Drive
HTTP GET, POST, PUT, DELETE to any API
Files Read, write, list
Database Query, insert, update

To see what your account has connected:

/credentials

To see all available action machines:

ask Koda: what integrations can I use?
/run email_triage

Give it “URGENT: Client unhappy” from a client email. Watch the Teams message appear in #ops-alerts.

Give it “Can you review this document?” from a colleague. Watch the Planner task get created.

Check the trace:

/timeline [run_id]

You will see:

[1] classify ask 420ms $0.0003 claude-haiku-4
[2] route decide 0ms $0.0000
[3] send_alert ask 850ms $0.0000 @mashin/actions/microsoft/graph/send_teams_message

The Teams call took 850ms and cost nothing (it is not an AI call). The whole triage took about 1.3 seconds.

You have a working email triage that classifies, routes, and acts. Next lesson: composing this into a clean multi-step flow and understanding how steps pass data to each other.

Next: Composition →