10. Prompts
A prompt is a named, parameterized template. Calling it interpolates parameters and returns a PromptInstance. await can call an LLM and validate JSON against a declared type. Decorators such as @within and @budget apply here as well as on functions — see 9.7 Decorators. Optional @version("…") is an informational pin for malda prompts --diff. Every await / Chat goes through cassettes when MALDA_RECORD / MALDA_REPLAY is set. .usage on a result is metadata (an own key named usage wins). Narrative: 24. Agentic Runs.
Templates without await are core language. await prompt, live LLM clients, and cassettes are host-only (interpreter and C# transpile). JavaScript can run validate / asVariant but not a live model call. See the backend capability matrix.
@version("2026-09-01")
prompt extract(raw) -> Card {
user: raw;
}
10.1 Overview
Prompt blocks are reusable prompt templates. Start with a template that does not call a model, then await with a schema, then tools. Same file as the course lesson: Examples/Basics/prompt_template.malda. Further files: Examples/Prompts/basic_prompt.malda, Examples/Prompts/schema_prompt_structured.malda, Examples/Prompts/prompt_tools_mode.malda, Examples/Prompts/prompt_tools_then_structured.malda.
await, tools, and cassettes stay in this chapter.
| Step | What you write | Calls a model? |
|---|---|---|
| 1. Template | prompt greet(name) { user: "Hello, {name}" } then greet("Alice") | No. You get a PromptInstance (interpolated strings). |
2. Structured await | schema + prompt ... -> Schema + await extract(...) | Yes. JSON is validated against the schema. |
| 3. Tools | Mode B: tools: [...] on one call. Mode C: gather: [...] then a typed extract | Yes. Do not combine tools: and gather:. |
Step 1 — template, no API key
prompt greet(name) {
user: "Hello, {name}! How are you today?"
}
var greeting = greet("Alice");
io.print(greeting.user);
Step 2 — await plus schema (needs an LLM)
schema ContactCard {
name: string;
email: string;
}
prompt extractContact(raw) -> ContactCard {
system: "Extract a contact. Reply with JSON only matching the schema.";
user: """
Text:
{raw}
"""
}
var card = await extractContact("Ada Lovelace — ada@example.com");
print("name=" + card.name);
Step 3 — Mode B vs Mode C
| Mode | Field | On await |
|---|---|---|
| B | tools: ["name"] | One LLM turn with tools. Schema response_format is not sent. |
| C | gather: ["name"] and -> Type | Tool round, then a fresh typed extract without tools. |
Without await, constructing the prompt still does not call the model. Details of validation, repair, pipes, and PromptInstance follow in this chapter.
10.2 Prompt Declaration Syntax
Prompts support two body syntaxes:
Object Literal Syntax (Backward Compatible)
prompt name(params) -> ReturnType? {
system: "Optional system prompt"
user: "Required user prompt with {parameter} interpolation"
model: "Optional model name"
temperature: 0.7
tools: ["tool1", "tool2"]
gather: ["read_file", "grep"]
maxTokens: 2000
}
Statement-Based Syntax (New)
prompt name(params) -> ReturnType? {
system "Optional system prompt";
user expression;
model "Optional model name";
temperature 0.7;
tools ["tool1", "tool2"];
gather ["read_file", "grep"];
maxTokens 2000;
}
Key Features:
- Parameters: Like functions, prompts can take parameters that are interpolated into the prompt strings
- Return Type: Optional annotation (
-> ReturnType). Forprompt(...)(withoutawait) it only affects the type of thePromptInstance. When you useawait prompt(...), the return type is enforced: the LLM response is parsed as JSON, validated against the declared type (primitives,Plan, or custom class names), and on repeated validation failure a repair instruction is sent and the call is retried (bounded attempts); after exhaustion a runtime error is thrown. Custom class return types (e.g.-> MyClass) are supported in both interpreted and transpiled runs. - Body: Two syntaxes supported:
- Object literal: Traditional syntax with
key: valuepairs - Statement-based: New syntax with
keyword expression;statements. Theuserfield can be any expression (converted to string), not just string literals.
- Object literal: Traditional syntax with
- Prompt Fields:
system/system:(optional string) - System prompt for the LLMuser/user:(required) - User prompt. In statement syntax, can be any expression (converted to string). Supports{param}interpolation and$"..."interpolated strings.model/model:(optional string) - LLM model nametemperature/temperature:(optional number) - Temperature setting for the LLMtools/tools:(optional array of strings) - List of tool names to make available (Mode B). Do not combine withgather.gather/gather:(optional array of strings) - Mode C marker: onawaitwith-> Type, run a tool round, then a fresh typed extract without tools. Requires-> Type. Constructing thePromptInstancewithoutawaitdoes not call the model.maxTokens/maxTokens:(optional integer) - Maximum tokens for the responseexamples/examples:(optional array) - Few-shot example pairs injected as user/assistant messages before the finaluserprompt. Each entry is an object withinputandoutputstrings (aliasesuser/assistantare accepted).attachments/attachments:(optional array) - Image and PDF parts sent with the user message onawait/runPrompt/agent.think.userandsystemstay strings. Each item is{ kind: "image" \| "pdf", path }or{ kind: "image", url }(http/https, passed through — the host does not fetch). Omitkindto infer from.png/.jpg/.jpeg/.webp/.gif/.pdf.pathmay be a string or acap.fileReadtoken. Constructing thePromptInstancestores metadata only; bytes are read at execution. HTTP clients send OpenAIimage_url/filecontent parts. In-process GGUF throws. Max 8 items, 10 MB each. SeeExamples/Prompts/multimodal_attachments.malda.
Few-Shot Examples
prompt classify(text) {
system: "Classify sentiment as positive or negative."
examples: [
{ input: "I love it!", output: "positive" },
{ input: "Terrible.", output: "negative" }
]
user: "Classify: {text}"
}
var p = classify("Pretty good");
print(length(p.examples)); // 2
When the prompt is executed (via agent.think, await prompt(...), or runPrompt), each example is sent as a user message followed by an assistant message, then the interpolated user field.
Multimodal attachments
prompt look(name) {
user: "Describe {name}"
attachments: [
{ path: "shots/{name}.png" }
]
}
var p = look("cat");
print(p.attachments[0].kind);
The instance stores metadata only. On await, HTTP clients send OpenAI content parts; in-process GGUF throws. Same file: Examples/Prompts/multimodal_attachments.malda.
Dynamic Few-Shot at Runtime
Use withExamples() to attach or replace examples on a PromptInstance built at runtime. Works in pipe pipelines:
prompt classify(text) {
user: "Classify: {text}"
}
var dynamic = [
{ input: "Great!", output: "positive" },
{ input: "Awful.", output: "negative" }
];
var p = classify("Pretty good") |> withExamples(dynamic);
// merge static + runtime examples from the prompt declaration:
var merged = withExamples(classify("x"), dynamic, { merge: true });
await (p |> runPrompt(client));
10.3 Basic Prompt Examples
Simple Prompt
prompt simple(task) {
user: "Task: {task}"
}
var p = simple("Add logging");
print(p.user); // Output: Task: Add logging
Prompt with System Message
prompt planTask(task, docs) -> Plan {
system: "You are a senior MALDA engineer specializing in feature planning.",
user: """
Implement feature: {task}
Relevant documentation:
{docs}
Provide a detailed implementation plan.
"""
}
var plan = planTask("Add error handling", readFile("docs.md"));
Prompt with Interpolation
prompt greet(name, age) {
user: $"Hello {name}, you are {age} years old."
}
var greeting = greet("Alice", 25);
10.4 Using Prompts with Agents
Prompt blocks can be passed directly to agent.think():
var client = new OpenRouterClient("openai/gpt-4");
var agent = new CodingAgent("Dev", "developer", "");
prompt codeReview(code, language) {
system: "You are an expert code reviewer.",
user: """
Review this {language} code:
```{language}
{code}
```
Provide:
1. Bug findings
2. Performance issues
3. Style suggestions
"""
}
var review = agent.think(codeReview(sourceCode, "malda"));
print(review.content);
When a PromptInstance is passed to agent.think():
- The
systemprompt (if provided) is set on the conversation - The
userprompt is used as the message - Optional metadata (
model,temperature,tools,maxTokens) can be applied (future enhancement)
10.5 Direct Await Execution
Prompts can be executed directly using await, which calls the LLM and returns the response string:
// Optional: use OpenRouter; omit to use default local LLM
var client = new OpenRouterClient();
var agent = new Agent("Assistant", "helper", "You are helpful.", client);
setDefaultAgent(agent);
prompt summarize(text) {
system "You are a summarizer. Respond with only the summary.";
user "Summarize: " + text;
}
var summary = await summarize("Long document text here...");
print(summary); // Prints the LLM response directly
How it works:
- When you use
await prompt(...), the prompt is executed immediately - The system uses the default agent (set via
setDefaultAgent(agent)) or creates a temporary agent with the default local LLM (Qwen/Qwen2.5-0.5B-Instruct, downloaded as a GGUF build from Hugging Face on first use) if none is set - If no return type is declared, the LLM response content is returned as a string
- If a return type is declared (
prompt name(...) -> Type), the return value is enforced: MALDA extracts JSON from the response (including from markdown or code fences), validates it against the declared type schema, and returns the parsed value on success - Mode A (structured): when
-> Typeis present and the prompt body has nogather:, the JSON schema is sent to the LLM backend (e.g. OpenAIresponse_format) so the model returns schema-conforming JSON on the first attempt. The same gate also appends a compact schema appendix to the system message (markerMALDA_OUTPUT_SCHEMA). In-process GGUF (LLamaSharp / llama.cpp) converts that schema to a GBNF grammar and constrains sampling (Mode A and Mode C extract; not Mode B tool rounds). Validate/repair still run after the reply. SeeExamples/Prompts/schema_prompt_structured.malda. - Mode B (tools):
tools:+-> Typeis still one LLM call (not two). MALDA sendsresponse_formatand the schema appendix together with tools. If the backend rejects tools+json_schema, the host retries once without format (keeps tools) and remembers that backend so later rounds skip the failed request. Onawait, validation and repair still run. SeeExamples/Prompts/prompt_tools_mode.malda. - Mode C (gather-then-extract):
gather: ["tool", …]plus-> Typeon one prompt. Onawait, MALDA runs a tool round (noresponse_format), then a fresh typed prompt without tools (Mode A validate/repair). Gather output is not passed tovalidateuntil the extract step. Offlineprompt(...)withoutawaitdoes not call the model. SeeExamples/Prompts/prompt_tools_then_structured.malda. The older two-prompt ritual still works; prefergather:. - On validation failure, MALDA appends a repair instruction to the prompt and retries (up to a fixed maximum of attempts); after exhaustion, a runtime error is thrown
- Supported return types include primitives (
string,int,number,bool,array,object), the built-inPlantype, custom class names (e.g.-> MyClass),schemanames, sum types (e.g.-> Intent), and programs (-> program(ApiName)); these work in both interpreter and transpiled mode - This provides a cleaner syntax than
agent.think(prompt(...)).content
10.6 Schema Declarations for Structured Output
Syntax, field types, validate, and the parseJSON / parseJson distinction live in 4.6 Schema declarations. This section is the prompt-shaped use: typed returns and parseJson after a model (or fixture) payload.
Declare reusable JSON schemas with the schema keyword. Schemas are used by parseJson() and typed prompt returns (-> Type):
schema Answer {
text: string;
sources: string[]; // array types: elementType[]
score: float?; // optional field
}
schema Address {
city: string;
}
schema Person {
name: string;
address: Address; // nested schema (expanded for validate / typed prompts)
}
var parsed = parseJson('{"text":"hi","sources":["a.md"]}', "Answer");
Supported field types: JSON primitives (string, int, float, bool, object, array), array forms such as string[] or Address[], other declared schema names (nested objects are expanded inline), and declared sum types (intent: Intent / Intent[] — tagged JSON oneOf). Use ? after the type for optional fields. Unknown field type names error when the schema is resolved; cyclic schema references are rejected. See Examples/Basics/schema_nested_validate.malda and Examples/Basics/schema_sumtype_validate.malda.
For end-to-end RAG pipelines combining schemas, prompts, retrievers, and pipes, see Examples/Prompts/rag_pipeline.malda and 13. Built-in Functions (AI pipeline helpers).
10.7 Sum Types as Prompt Return Types
When the model must choose one of several shapes (intents), declare a sum type and use it as the prompt return type. On success, await returns a real variant value for match:
type Intent =
Search(query: string)
| Buy(sku: string, qty: int)
| Help();
prompt parseUtterance(text) -> Intent {
system: "Map the user to exactly one Intent variant. JSON only.";
user: text;
}
var intent = await parseUtterance("buy 2 of SKU-9");
match intent {
case Search(q): print("search: " + q);
case Buy(sku, qty): print("buy " + sku);
case Help(): print("help");
}
Wire JSON uses a tag field equal to the constructor name, plus payload fields named like the constructor parameters — for example {"tag":"Buy","sku":"SKU-9","qty":2} or {"tag":"Help"}. Optional payload types (Buy(sku: string, qty: int)) become JSON Schema types for validate, asVariant, typed prompts, and evalPrompt; name-only parameters stay permissive. The same name cannot be both a schema and a type (sum type). validate("Intent", dict) accepts that tagged shape and returns the original dict; it does not produce a variant. Use asVariant("Intent", dict) for match without await, or evalPrompt(instance, fixture) to fixture-test the same coerce path as await with no LLM. See Examples/Prompts/sum_type_intent_prompt.malda, Examples/Prompts/eval_prompt.malda, Examples/Basics/as_variant.malda, Examples/Basics/sumtype_typed_payloads.malda, Examples/Basics/schema_sumtype_validate.malda, and 4.5 Sum Types / 4.6 Schema.
10.8 Closed APIs and Deterministic Programs
Declare a closed api of method signatures. Implementations are ordinary top-level functions with the same names. Method parameters may optionally take a SchemaType (the same form as schema fields and sum-type payloads: add(a: number, b: number)); name-only stays permissive. Declared types feed the program JSON Schema and coerce LLM args ("2" becomes a number only when the hint is number/int). Prompt parameters stay name-only, and the implementing function body stays untyped. A typed prompt may return program(ApiName); on success you get a program value that runProgram executes with no further LLM calls (unlike @Tool agent loops or executePlan):
api Calc {
function add(a: number, b: number);
function mul(a: number, b: number);
}
function add(a, b) { return a + b; }
function mul(a, b) { return a * b; }
prompt solve(expr) -> program(Calc) {
system: "Translate into Calc steps. JSON only.";
user: expr;
}
var prog = await solve("(2 + 3) * 4");
var result = runProgram(prog);
Wire JSON shape. Offline (no LLM), pass the same object to runProgram directly — args are JSON literals or "$alias" references to a prior step's as. Models often emit nested {"call","args"}, TypeChat @func/@ref, numeric strings ("2"), or {"type":"number","value":2} wrappers; the host flattens and coerces those before calling the api methods. When methods are named _add/_mul, the host also maps unique aliases such as add/mul and +/*, and treats a bare t0 as "$t0". Leftover objects in args are rejected (they used to be passed through, so add received an object instead of a number). Prefer JSON numbers, not numeric strings:
api Calc {
function add(a: number, b: number);
function mul(a: number, b: number);
}
function add(a, b) { return a + b; }
function mul(a, b) { return a * b; }
var prog = parseJSON("""
{
"@api": "Calc",
"steps": [
{ "call": "add", "args": [2, 3], "as": "t0" },
{ "call": "mul", "args": ["$t0", 4], "as": "result" }
],
"return": "$result"
}
""");
var result = runProgram(prog);
print(result);
See Examples/Prompts/api_program_calc.malda. A name cannot be both an api and a schema / sum type.
Fixture-test the same coerce path with evalPrompt(solve(expr), fixture) (no LLM). On await, Mode A sends response_format and in-process GGUF applies a GBNF grammar from that schema. Few-shot: docs/llm/few-shot/28_api_program_prompt.malda.
For a durable agent, produce the program JSON before startWorkflow, then execute it in a memoized step. A step right-hand side is a single call, so the shape is step result = runProgram(prog);. Do not await a prompt in the workflow body: replay would call the model again, and that is not WF1001/WF1002. See Examples/Workflows/runprogram_in_step.malda and few-shot docs/llm/few-shot/29_runprogram_in_step.malda.
10.9 Reusable Pipe Pipelines
Name and reuse multi-step AI pipelines with ordinary function declarations and the pipe operator (|>). Return the final pipe result explicitly.
function ragContext(question, retriever) {
return question |> retriever.get |> formatRetrievedDocs;
}
function ragPrompt(question, context) {
return context |> (ctx) => answerPrompt(question, ctx);
}
var context = ragContext("What is GraphMemory?", retriever);
var prompt = ragPrompt("What is GraphMemory?", context);
With an LLM client and typed output:
function ragAnswer(question, client) -> Answer {
return question |> retriever.get |> formatRetrievedDocs
|> (ctx) => answerPrompt(question, ctx)
|> runPrompt(client)
|> parseJson("Answer");
}
var answer = await ragAnswer("How does retrieval work?", client);
Local bindings for readable multi-stage bodies (retrieval, branching, reuse of intermediate values):
function buildContext(question, retriever, fallback) {
var hits = question |> retriever.get;
if (length(hits) == 0) {
return fallback;
}
var text = formatRetrievedDocs(hits);
return text;
}
Stream tokens during runPrompt in interpreted and transpiled mode: pass { onToken: (token) => ... } for content and { onReasoning: (token) => ... } for reasoning deltas (see 10.9.1).
See 7. Expressions (pipe operator) and Examples/Prompts/rag_function_pipeline.malda.
Advanced composition: composePipe, parallelRun, and mergeRetrievedDocs compose with functions and pipes for parallel retrieval and reusable pipeline functions. See Examples/Prompts/rag_compose_pipeline.malda and the catalog below.
10.9.1 AI pipeline helpers
These built-ins compose with the pipe operator (|>) for retrieval-augmented generation (RAG) and structured LLM output. Indexing into a VectorDB: 16. VectorDB (asRetriever, indexInto). Offline fixtures: 13.7.1.2 evalPrompt. Worked files: Examples/Prompts/rag_pipeline.malda, Examples/Prompts/rag_compose_pipeline.malda.
// Load text files matching a glob pattern (default directory: current)
var docs = loadDocuments("**/*.md", "docs/");
// Split long documents into overlapping chunks
var chunks = splitDocuments(docs, 512, 64);
// Index documents into a VectorDB (embeds content, preserves metadata)
indexInto(vdb, chunks);
// Format retrieved documents for prompt context
var context = query |> retriever.get |> formatRetrievedDocs;
// Execute a PromptInstance with the default or supplied LLM client
var response = await (promptInstance |> runPrompt(client));
// Stream tokens while the model responds
var seen = "";
function onTok(token) { seen = seen + token; }
var response = await runPrompt(promptInstance, client, { onToken: onTok });
// Stream model reasoning/thinking deltas (OpenRouter-compatible providers)
var reasoning = "";
function onReason(token) { reasoning = reasoning + token; }
var response = await runPrompt(promptInstance, client, { onReasoning: onReason });
// Attach runtime few-shot examples to a prompt instance
var p = classify("query") |> withExamples(dynamicExamples);
// Validate LLM JSON output against a schema
var parsed = response |> parseJson("Answer");
// Advanced composition: sequence + parallel branches
var pipeline = composePipe(formatRetrievedDocs, (ctx) => answerPrompt(q, ctx));
var context = question |> pipeline;
var branches = parallelRun(question, {
context: (q) => q |> retriever.get,
tags: classifyIntent
});
var merged = mergeRetrievedDocs(branches.context, branches.tags);
| Function | Description |
|---|---|
loadDocuments(pattern, dirPath?) | Glob-matches files under dirPath (default "."); returns { content, metadata: { source } } per file |
splitDocuments(docs, chunkSize, overlap?) | Splits document content into overlapping chunks; copies metadata to each chunk |
indexInto(vdb, docs) | Embeds and adds each document to a VectorDB via its calculator; stores metadata with hits |
formatRetrievedDocs(docs) | Formats document arrays as [source: …] blocks joined for prompt context |
composePipe(step1, step2, …) | Composes 2+ callables (functions, lambdas, built-ins, prompts) left-to-right into a reusable function (input) => …. Awaits async steps. Pipe-friendly: input |> composePipe(f, g) |
parallelRun(input, branches) | RunnableParallel: feeds the same input to each named branch concurrently; returns an object/map of results. Use await when branches include async steps. |
mergeRetrievedDocs(docArrays…) | Flattens multiple Document[] arrays (e.g. from parallelRun) into one array; dedupes by source+chunk metadata or content |
withExamples(prompt, examples, options?) | Returns a copy of a PromptInstance with runtime few-shot examples. Pass { merge: true } to append after any static examples from the prompt declaration. Pipe-friendly. |
evalPrompt(prompt, fixture, typeName?) | Offline fixture in/out on a PromptInstance (no LLM). Returns { ok, data } or { ok: false, error }. data matches await (variant for sum types). Fixture: dict or LLM-shaped JSON string. instance.eval(fixture) is the same helper. See 13.7.1.2. |
runPrompt(prompt, client?, options?) | Async: runs a PromptInstance through an LLM; returns response text. Optional options: { onToken: (token) => ... } for streamed content tokens; { onReasoning: (token) => ... } for streamed reasoning/thinking tokens. Both work in interpreted and transpiled mode with await and pipe steps. |
parseJson(json, schemaName) | Parses and validates JSON against a schema declaration; returns a typed object |
Name index: 13.7.2.
Typed Await Example (Validated Output)
prompt planTask(task) -> Plan {
system "You are a planner. Return only JSON.";
user "Task: " + task;
}
// With a return type, await validates the model output
var plan = await planTask("Add parser tests");
print(plan.steps[0].description);
Setting a Default Agent:
If you omit a client, the default is the local Qwen/Qwen2.5-0.5B-Instruct model (auto-downloaded as a GGUF build from Hugging Face). To use a remote model (e.g. OpenRouter), pass a client:
// Optional: use OpenRouter for remote model
var client = new OpenRouterClient();
var agent = new Agent("MyAgent", "assistant", "You are helpful.", client);
setDefaultAgent(agent);
// Now await prompt() calls will use this agent
var result = await myPrompt("input");
10.10 PromptInstance Properties
When a prompt is invoked, it returns a PromptInstance object with the following properties:
var p = myPrompt("arg1", "arg2");
// Access prompt fields
var system = p.system; // string? (null if not provided)
var user = p.user; // string (required)
var examples = p.examples; // array? of { input, output } few-shot pairs
var model = p.model; // string? (null if not provided)
var temperature = p.temperature; // number? (null if not provided)
var tools = p.tools; // array? (null if not provided; Mode B)
var gather = p.gather; // array? (null if not provided; Mode C tool list)
var maxTokens = p.maxTokens; // number? (null if not provided)
var returnType = p.returnType; // string? declared -> Type (null if untyped)
// Methods
var userStr = p.getUser(); // Returns user prompt string
var systemStr = p.getSystem(); // Returns system prompt string or null
var promptStr = p.toPromptString(); // Returns user prompt (for backward compatibility)
var checked = p.eval(dict { "name": "Ada" }); // Offline fixture in/out; same as evalPrompt(p, fixture)
evalPrompt(instance, fixture, typeName?) (and instance.eval) feed simulated model JSON through the same extract / validate / coerce path as await, with no LLM and no repair loop. Success data for a sum type is a variant for match. See 13.7.1.2 evalPrompt and Examples/Prompts/eval_prompt.malda.
10.11 Advanced Prompt Features
Prompt with Metadata (Object Literal Syntax)
prompt advanced(task) {
system: "You are an expert.",
user: "Task: {task}",
model: "openai/gpt-4",
temperature: 0.7,
tools: ["read_file", "write_file", "grep"],
maxTokens: 2000
}
Prompt with Metadata (Statement-Based Syntax)
prompt advanced(task) {
system "You are an expert.";
user "Task: " + task;
model "openai/gpt-4";
temperature 0.7;
tools ["read_file", "write_file", "grep"];
maxTokens 2000;
}
Statement-Based Syntax with Expressions
The statement-based syntax allows user to be any expression, not just a string literal:
prompt combine(a, b) {
user "First: " + a + ", Second: " + b;
}
var result = combine("A", "B");
print(result.user); // Output: First: A, Second: B
Multi-line Prompts
prompt detailedPlan(goal, context) {
system: "You are a strategic planner.",
user: """
Goal: {goal}
Context:
{context}
Please provide:
1. Step-by-step plan
2. Risk assessment
3. Timeline estimate
"""
}
10.12 Prompt Blocks vs String Concatenation
Before (String Concatenation):
var prompt = "Task: " + task + "\n\n" +
"Documentation:\n" + docs;
var response = agent.think(prompt);
After (Prompt Blocks):
prompt planTask(task, docs) {
user: """
Task: {task}
Documentation:
{docs}
"""
}
var response = agent.think(planTask(task, docs));
Benefits:
- Structure: Prompts are named, parameterized functions
- Reusability: Define once, use anywhere
- Parameter Validation: Runtime validates argument count matching
- IDE Support: Autocomplete, go-to-definition, refactoring
- Maintainability: Version prompts independently, test variations easily
See Also
- 9. Functions - Parameters, return, lambdas, and decorators
- 4.5 Sum Types / 4.6 Schema — syntax for
typeandschema - 7. Expressions - Pipe operator for prompt pipelines
- 13. Built-in Functions - AI pipeline helpers
- 19. Agent Orchestration - Using agents with prompts
- 24. Agentic Runs -
@version,.usage, cassettes,malda eval