Actions
Ce contenu n’est pas encore disponible dans votre langue.
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 … from
Section titled “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
Section titled “Calling stdlib machines”mashin provides a standard library of actions 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
Section titled “Common 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
Section titled “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
Section titled “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 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.
Polyglot execution
Section titled “Polyglot execution”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.5This ensures all external code runs through the governance boundary. The runtime checks permissions, records the execution, and tracks the result.
Interpretation modes
Section titled “Interpretation modes”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.
Governance
Section titled “Governance”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
Section titled “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
Section titled “Next steps”- Memory - Semantic storage and retrieval
- Composition - Building machines from machines
- ask … from reference - Full specification