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 GETask 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 POSTask 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: 201Common stdlib machines
| 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 |
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.recordA 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.5This 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 itask description, from: email_triage, to: explain
// Estimate cost without runningask projection, from: email_triage, to: cost
// Run with mocked effectsask dry_run, from: email_triage, to: simulateGovernance
Every ask ... from step is governed:
- The machine must have
machine.callpermission (or the specific capability the target requires) - The call emits a directive mediated by the governance interpreter
- The target machine, inputs, and result are recorded in the behavioral ledger
- 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
- Memory - Semantic storage and retrieval
- Composition - Building machines from machines
- ask … from reference - Full specification