Zum Inhalt springen
Developer Preview — APIs and language features may change before 1.0

Inputs and Outputs

Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.

Every machine has a contract: what data it takes in (accepts) and what data it returns (responds with). The runtime validates incoming data against this contract before any step runs. If a required field is missing or a constraint is violated, execution is rejected immediately. No steps execute, no tokens are spent, no ledger entries are created.

accepts
name as text, is required
email as text, is required, format: "email"
age as integer, min: 13
role as text, default: "member", choices: ["member", "admin", "moderator"]

Each field has three parts: a name, a type (after as), and optional modifiers.

Type Description
text / string Text value
number Numeric (integer or decimal)
integer Integer only
decimal Decimal/float
boolean True or false
list Array of values
list of <type> Typed list (e.g., list of text)
map Key-value object
any Untyped

is required makes a field mandatory. default: <value> provides a fallback when the field is not supplied.

accepts
query as text, is required
limit as number, default: 10
include_archived as boolean, default: false

Constraints catch bad data before it reaches your steps:

accepts
username as text, is required, min_length: 3, max_length: 20, pattern: "^[a-zA-Z0-9_]+$"
score as number, range: 0.0..1.0
priority as text, choices: ["low", "medium", "high", "urgent"]
tags as list, subset: ["bug", "feature", "docs"]
Constraint Applies to Meaning
min: / max: numbers Value bounds
min_length: / max_length: text String length bounds
format: text Named format (e.g., "email")
pattern: text Regex match
choices: text Allowed values
range: lo..hi numbers Value within range
responds with
summary as text
confidence as number
tags as list of text

The runtime validates that the machine’s final output matches this contract. Extra fields are stripped. Missing fields cause an error.

You can map output fields directly to step results instead of writing a final compute step:

responds with
answer as text, from search
sources as list, from search
cached as boolean, from state.was_cached, default false

Without from, output fields are populated from the last step’s return value by matching field names.

Inside any step, use input.<field> to access input values:

compute greet
{greeting: "Hello, " + input.name + "!"}

Inside ask steps, interpolate inputs into the task string:

ask classify, using: "anthropic:claude-sonnet-4-6"
with task "Classify this text: ${input.text}\nMax categories: ${input.limit}"
machine user_profile_validator
accepts
email as text, is required, format: "email"
username as text, is required, min_length: 3, max_length: 30
age as integer, is required, min: 13, max: 150
bio as text, max_length: 500
interests as list of text
responds with
valid as boolean
profile_summary as text
warnings as list of text
behaves
compute validate_and_summarize
let warnings = []
let bio_text = input.bio || "No bio provided"
let interest_count = input.interests ? input.interests.length : 0
{
valid: true,
profile_summary: input.username + " (" + input.email + "), age " + input.age + ", " + interest_count + " interests",
warnings: interest_count == 0 ? ["No interests listed"] : []
}
verifies
test "summarizes a complete profile"
given {email: "[email protected]", username: "ada", age: 36, interests: ["math"]}
expect {valid: true, profile_summary: "ada ([email protected]), age 36, 1 interests", warnings: []}

The accepts section handles type checking and constraint validation. By the time compute runs, you know the data is clean.

Create a machine that accepts an email address (with format validation), a message body (with a max_length of 1000), and a priority field (with choices). Have it use a compute step to build a formatted output. Try invoking it with invalid data and observe the validation error.