Cookbook

On this page

Practical recipes, each grounded in what the implementation actually supports.

Recipe: Deterministic prompts for testing

Disable caching and auto-detection so build() output is a pure function of its explicit arguments:

Python · 2 lines
engine = PromptEngine(enable_cache=False, enable_auto_detect=False)
prompt = engine.build(query="What is RAG?", strategy="simple", prompt_type="qa")

Recipe: Observability dashboard feed

Python · 5 lines
def snapshot(engine: PromptEngine) -> dict:
    return {
        "metrics": engine.metrics,
        "recent_traces": engine.get_trace_log(last_n=50),
    }

Feed snapshot(engine) into your metrics pipeline on a timer. See api/prompt_engine for the exact shape.

Recipe: Quality feedback loop

Python · 10 lines
prompt = engine.build(query=q, documents=docs, trace_id=str(uuid.uuid4()))
response = llm.chat(prompt.to_messages())

# ... collect a quality signal (user thumbs-up/down, automated eval, etc.) ...
engine.record_feedback(trace_id=prompt.trace_id, quality_score=1.0 if thumbs_up else 0.0)

# Periodically:
suggested = engine.adaptive_strategy_for(PromptType.QA)
if suggested:
    logger.info("Adaptive suggestion for QA: %s", suggested.value)

Remember: adaptive_strategy_for only returns a suggestion once 5+ feedback entries exist for that prompt_type, and you must manually pass its result into future build(strategy=...) calls — nothing applies it automatically (see api/prompt_engine.md#adaptive-feedback).

Recipe: Strict grounding for compliance-sensitive answers

Python · 8 lines
prompt = engine.build(
    query=user_query,
    documents=retrieved_docs,
    enable_guardrails=True,
    enable_citations=True,
    enable_uncertainty=True,
    output_format="citation",
)

This combination applies GROUNDING, NO_FABRICATION, UNCERTAINTY, CITE_SOURCES, PII_PROTECTION, STAY_ON_TOPIC, SAFE_OUTPUT, and CONCISE (see the selection table in api/guardrails), plus the citation-format instruction requiring a trailing Sources section.

Recipe: Agent / tool-use prompts

Python · 8 lines
prompt = engine.build(
    query="Find me a flight to Cairo next Tuesday under $500.",
    prompt_type="agent",
    extra={"tools": [
        {"name": "search_flights", "description": "Search flights by route/date/budget",
         "parameters": {"origin": "string", "destination": "string", "date": "string", "max_price": "number"}},
    ]},
)

prompt_type="agent" defaults to strategy=REACT (see api/builder.md#default-strategy-table), and ReActStrategy renders an ## Available Tools section only when extra["tools"] is present (see api/strategies).

Recipe: Batch processing many queries efficiently

Python · 3 lines
engine = PromptEngine(enable_cache=True, max_cache_size=1000)  # raise cache ceiling for a large batch

prompts = [engine.build(query=q, documents=retrieve(q)) for q in queries]

Caching helps most when the same (query, doc-snippet, type, strategy, format, language) combination recurs — see the cache-key composition caveat in api/prompt_engine (document metadata and conversation history are not part of the key).

Recipe: Comparing two system-prompt strategies before shipping

See the dedicated A/B Testing tutorial.

Recipe: Keeping prompts within a hard model context window

Python · 6 lines
from zerda.prompt.optimizer import PromptOptimizer

# strategies build their own PromptOptimizer() internally with defaults;
# if you need a different cap, apply a second pass yourself:
opt = PromptOptimizer(max_total_tokens=4000)
system, user, saved, notes = opt.optimize(prompt.system_prompt, prompt.user_prompt)

Strategies always construct a default-configured PromptOptimizer() internally (see api/strategies.md#basestrategy) — there's no way to pass optimizer settings through PromptEngine.build(). If you need a non-default max_total_tokens, re-run optimization yourself as shown, or lower max_context_tokens on the request to reduce how much context is assembled in the first place.

Related pages