Ir al contenido
Developer Preview — APIs and language features may change before 1.0

Actions

Esta página aún no está disponible en tu idioma.

In mashin, code computes and machines act. Pure computation happens in compute steps. All external interaction (HTTP requests, file operations, database queries, calling other machines) is expressed as an intent. The program never performs the action directly; the runtime mediates each intent through governance before executing it. Action machines are the governed boundary where intents become actions. The primary syntax is ask ... from, which calls an action machine and returns structured output.

ask <name>, from: "<machine_path>"
<input_key>: <value>
returns
<field> as <type>
assuming
<field>: <mock_value>

The from parameter specifies which machine to call. It can be a stdlib machine, an organization machine, or a local machine.

mashin provides a standard library of actions under @mashin/actions/:

// HTTP GET
ask fetch_data, from: "@mashin/actions/http/get"
url: "https://api.example.com/data"
headers: {"Authorization": "Bearer " + input.api_key}
returns
body as map
status as number
assuming
body: {items: [{id: 1, name: "Item 1"}]}
status: 200
// HTTP POST
ask submit, from: "@mashin/actions/http/post"
url: "https://api.example.com/orders"
body: {customer: input.customer_id, items: input.items}
returns
order_id as text
status as number
assuming
order_id: "ord_123"
status: 201
Machine Purpose
@mashin/actions/http/get HTTP GET request
@mashin/actions/http/post HTTP POST request
@mashin/actions/file/read Read a file
@mashin/actions/file/write Write a file
@mashin/actions/exec/* Execute commands
@mashin/actions/python/exec Run Python code
@mashin/actions/javascript/exec Run JavaScript code
@mashin/actions/notifications/send Send notifications

Machines can call other machines you have written or published:

ask validate, from: "@myorg/orders/validate"
order_id: input.order_id
returns
valid as boolean
errors as list
assuming
valid: true
errors: []

Local machines (in the same project) can be referenced by name:

ask enrich, from: "data_enricher"
record: input.record
machine data_pipeline
accepts
source_url as text, is required
target as text, is required
responds with
records_processed as number
status as text
behaves
ask fetch_data, from: "@mashin/actions/http/get"
url: input.source_url
returns
body as map
status as number
compute transform
let records = steps.fetch_data.body.records
let cleaned = records.filter(r => r.value != null)
{cleaned: cleaned, count: cleaned.length}
ask store, from: "@myorg/data/writer"
target: input.target
records: transform.cleaned
compute result
{records_processed: transform.count, status: "complete"}
ensures
permissions
allowed to
network.http to any
call
verifies
test "fetches, cleans, and stores records"
assuming fetch_data {body: {records: [{id: 1, value: "test"}, {id: 2, value: null}]}, status: 200}
assuming store {written: true}
given {source_url: "https://example.com/data", target: "warehouse"}
expect {records_processed: 1, status: "complete"}

This machine fetches data via HTTP, transforms it in a pure compute step, stores it by calling another machine, and returns a summary.

External language execution (Python, JavaScript, Rust) is a governed action. You call a language executor machine:

ask analyze, from: "@mashin/actions/python/exec"
code: "import pandas as pd\ndf = pd.DataFrame(data)\nresult = {'mean': df['value'].mean()}"
data: input.dataset
returns
mean as number
assuming
mean: 42.5

This ensures all external code runs through the governance boundary. The runtime checks permissions, records the execution, and tracks the result.

Analyzing a machine instead of running it (explain, cost, simulate, evaluate, verify, improve) is a machine call, not a grammar form on ask ... from. There is no to: parameter. Internal canon: docs/architecture/2026-07-12_ADR_INTERPRETATION_MODES.md (founder ruling, GAP-927 deferred). Call the analyzer like any other machine, passing the target machine’s source or reference as input:

machine machine_optimizer
achieves
goal "Analyze a target machine and say whether it needs improvement"
succeeds when "the verdict cites the quality score it was based on"
never "modify the target without a governed proposal"
accepts
target_ref as text, is required
target_source as text, is required
min_score as number, default: 7
responds with
report as map
behaves
// Structural description of the target, read from its form (no execution)
ask description, from: "@system/koda/form_describe"
machine_ref: input.target_ref
// Quality score across syntax, structure, governance, testing, composition
ask quality, from: "@system/koda/evaluate"
machine_source: input.target_source
compute report
let needs_work = quality.overall_score < input.min_score
{report: {name: description.form.name, score: quality.overall_score, needs_improvement: needs_work}}
verifies
test "a healthy machine needs no improvement"
assuming description {form: {kind: "machine", name: "email_triage"}, capabilities: [], is_valid: true}
assuming quality {overall_score: 9, valid_syntax: true, improvement_suggestions: []}
given {target_ref: "@myorg/email_triage", target_source: "machine email_triage"}
expect {report: {name: "email_triage", score: 9, needs_improvement: false}}
test "a low-scoring machine is flagged"
assuming description {form: {kind: "machine", name: "email_triage"}, capabilities: [], is_valid: true}
assuming quality {overall_score: 3, valid_syntax: true, improvement_suggestions: ["add tests"]}
given {target_ref: "@myorg/email_triage", target_source: "machine email_triage"}
expect {report: {name: "email_triage", score: 3, needs_improvement: true}}

The six modes are reached two ways: as Koda slash commands (/explain email_triage, /cost email_triage, /simulate email_triage, /evaluate email_triage, /verify email_triage, /improve email_triage) and as machine calls like the one above. A custom analyzer is a plain machine that takes a machine’s form or source as input; nothing about it is privileged, and assuming mocks it in tests exactly like any other ask ... from: step.

Every ask ... from step is governed:

  1. The machine must have machine.call permission (or the specific capability the target requires)
  2. The call emits a directive mediated by the governance interpreter
  3. The target machine, inputs, and result are recorded in the behavioral ledger
  4. The called machine runs under its own governance rules (governance does not leak across boundaries)

In test mode, assuming values are returned instead of calling the real machine.

Write a machine that fetches weather data from an HTTP API, uses an LLM to summarize the forecast in plain language, and returns the summary. Use ask ... from for the HTTP call and ask ... using for the LLM.