The infer Primitive
infer is the most important statement in Turn. It is the boundary between deterministic computation and stochastic intelligence — and it is a first-class language construct, not a function call.
What infer Actually Does
In most frameworks, LLM inference looks like this:
response = llm.chat("Analyze this review: " + review)
# response is a str. You parse it. You hope it's JSON. You handle ValueError.In Turn, infer is a typed statement:
struct Sentiment {
score: Num,
label: Str,
reasoning: Str
};
let result = infer Sentiment { "I love this product!"; };
// result.score is a Num. result.label is a Str.
// The VM guarantees structural correctness — not just at runtime, but semantically.The difference is not syntactic sugar. infer is a VM trap — it suspends the process, delegates computation to a sandboxed Wasm provider, validates the response against a compile-time JSON Schema, and resumes with a structurally guaranteed value.
Cognitive Type Safety
When you write infer Sentiment { ... }, the Turn compiler does something remarkable at compile time: it generates a full JSON Schema from the Sentiment struct definition and bakes it into the bytecode as part of the inference call.
This schema travels to the LLM provider as a response_format constraint. The model is forced to produce output that matches it. The Turn VM validates the JSON before binding it to your type.
struct Analysis {
summary: Str,
confidence: Num,
tags: List, // List of strings
action: Str
};
let doc = "Q4 revenue declined 12%, primarily driven by slowing enterprise deals in APAC.";
let result = infer Analysis {
"Analyze this business document and extract the key findings: " + doc;
};
// All fields are fully typed — no parsing, no casting
call("echo", "Summary: " + result.summary);
call("echo", "Confidence: " + result.confidence);
call("echo", "Action: " + result.action);
// Structured access to list fields
if result.confidence < 0.6 {
call("echo", "⚠ Low confidence — human review recommended");
}If infer Struct { ... } completes without error, the bound value structurally conforms to the declared type. Field names, types, and nesting are all guaranteed. A field access on an infer result cannot produce a type mismatch at runtime.
Anatomy of an infer Statement
let <binding> = infer <Type> {
<prompt_expression>;
};The prompt expression can be any Turn expression that evaluates to a string. You can concatenate variables, format values, and compose prompts dynamically:
let user_query = recall("last_question");
let product_name = recall("product");
let result = infer Summary {
"Summarize the following user question about " + product_name + ": " + user_query;
};Inference Without a Schema (Free-Form)
When you don't need a typed response, you can infer without a struct. The result is a raw string:
let poem = infer {
"Write a haiku about distributed systems.";
};
call("echo", poem);Use this sparingly. Whenever the output will be used in your code — compared, assigned to a struct field, or returned — prefer a typed infer so the VM can enforce correctness.
Context and Working Memory in Prompts
The Turn VM automatically enriches infer calls with the agent's context window. Anything you've appended with context.append() is included in the prompt, in priority-stack order.
context.append("You are an expert financial analyst.");
context.append("Clients have conservative risk profiles.");
// The LLM receives the context above + the user prompt
let result = infer Portfolio {
"Allocate $50,000 across 5 asset classes for a 10-year growth horizon.";
};The Turn VM also performs Semantic Auto-Recall: before every infer call, it queries the HNSW semantic memory graph for the 3 most similar previous memories and prepends them to the context payload automatically. This gives agents temporal awareness without manual wiring.
Handling Inference Errors
infer is stochastic — the model might fail, the provider might be rate-limited, or the schema validation might fail on a malformed response. Use Turn's Result pattern:
let result = infer Sentiment { review; };
if result == null {
call("echo", "Inference returned null — retrying with clearer prompt");
return;
}
call("echo", "Score: " + result.score);NOTE
Full Result<T, E> monadic error handling for infer is covered in the Error Handling section.
Performance Characteristics
infer suspends the Turn process (not an OS thread) while the HTTP call is in flight. The VM serializes its continuation and the Tokio scheduler picks up other work. From the programmer's perspective, infer is synchronous; from the runtime's perspective, it is fully async.
- Cold start: ~0μs (Wasm module is pre-loaded at VM startup)
- Network round-trip: depends on provider and model
- Schema validation: O(n) in response size, typically under 1ms
Next Steps
- Inference Providers — How the Wasm sandbox works, which providers are available, and how to write your own
- Memory & Context — How semantic recall enriches your
infercalls automatically - Types & Errors — Cognitive types,
Result, andconfidencetraps