Skip to content

Effects

In mashin, code computes and machines effect. Pure computation happens in compute steps. All external interaction (HTTP requests, file operations, database queries, calling other machines) happens through governed effect steps. The primary syntax for this is ask ... from, which calls an effect machine and returns structured output.

ask … from

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.

Calling stdlib machines

mashin provides a standard library of effect machines 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

Common stdlib machines

MachinePurpose
@mashin/actions/http/getHTTP GET request
@mashin/actions/http/postHTTP POST request
@mashin/actions/file/readRead a file
@mashin/actions/file/writeWrite a file
@mashin/actions/exec/*Execute commands
@mashin/actions/python/execRun Python code
@mashin/actions/javascript/execRun JavaScript code
@mashin/actions/notifications/sendSend notifications

Calling your own machines

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

A complete example

machine data_pipeline
accepts
source_url as text, is required
target as text, is required
responds with
records_processed as number
status as text
ensures
permissions
allowed to
http, machine.call
implements
ask fetch_data, from: "@mashin/actions/http/get"
url: input.source_url
returns
body as map
status as number
assuming
body: {records: [{id: 1, value: "test"}]}
status: 200
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
assuming
written: true
compute result
{records_processed: transform.count, 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.

Polyglot execution

External language execution (Python, JavaScript, Rust) is a governed effect. 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.

Interpretation modes

ask ... from supports a to: parameter that changes how the target machine is processed:

// Explain what a machine does without executing it
ask description, from: email_triage, to: explain
// Estimate cost without running
ask projection, from: email_triage, to: cost
// Run with mocked effects
ask dry_run, from: email_triage, to: simulate

Governance

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.

Try it

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.

Next steps