Cookbook¶
Short, copy-paste recipes for the tasks you'll reach for most. Each is the minimal correct form; follow the link for the full guide.
Every agent capability is one parameter on build_agent() — enable only
what you need; the rest has zero overhead.
Agent recipes¶
Add persistent memory¶
Remember context across invocations; relevant past context is auto-injected.
from promptise.memory import ChromaProvider
agent = await build_agent(model="openai:gpt-5-mini", servers=srv,
memory=ChromaProvider(persist_directory="./memory"))
Persist conversations (with ownership)¶
chat() loads history, invokes, and saves — and enforces session ownership.
from promptise.conversations import SQLiteConversationStore
agent = await build_agent(model="openai:gpt-5-mini", servers=srv,
conversation_store=SQLiteConversationStore("chat.db"))
reply = await agent.chat("hi", session_id="s1", caller=caller)
Cache similar queries¶
Serve semantically-similar queries from cache (30–50% cost reduction).
from promptise.cache import SemanticCache
agent = await build_agent(model="openai:gpt-5-mini", servers=srv, cache=SemanticCache())
Add security guardrails¶
Block prompt injection on input; redact PII/credentials on output. Models run locally.
→ GuardrailsAttach per-request identity¶
Carry the user through the whole invocation (cache/memory/conversation scope, audit).
from promptise import CallerContext
await agent.ainvoke(input, caller=CallerContext(user_id="alice", roles=["analyst"]))
Isolate by tenant (multi-tenant SaaS)¶
Add tenant_id — every isolation surface (cache, memory, conversations) scopes to it.
Compute over data with one program¶
For sums/joins/multi-hop aggregation, the model writes one sandboxed Python program.
→ Code-ActionSandbox code execution¶
Run agent-written code in a hardened Docker sandbox (seccomp, dropped caps, no network).
→ SandboxTrace everything¶
Record every LLM turn, tool call, token, and latency.
→ ObservabilityMCP server recipes¶
Define a tool¶
Schema is generated from type hints.
from promptise.mcp.server import MCPServer
server = MCPServer(name="api")
@server.tool()
async def search(query: str, limit: int = 10) -> list:
"""Search records."""
return await db.search(query, limit)
Require authentication + a role¶
from promptise.mcp.server import JWTAuth, AuthMiddleware
server.add_middleware(AuthMiddleware(JWTAuth(secret="...")))
@server.tool(auth=True, roles=["admin"])
async def delete_all() -> str: ...
Rate-limit a tool¶
Declared limits are enforced automatically (per client, tenant-qualified).
→ Caching & PerformanceRequire human approval for a tool¶
Server-side, for any MCP client. Fail-closed; four-eyes enforced.
from promptise.mcp.server import ApprovalGateMiddleware, PendingApprover
approver = PendingApprover(server, approver_role="approver")
server.add_middleware(ApprovalGateMiddleware(approver, timeout=300))
@server.tool(auth=True, requires_approval=True)
async def refund(order_id: str, amount: float) -> dict: ...
Make tenancy a server-wide invariant¶
Every tool authenticates and must carry a tenant, or the call is denied.
server = MCPServer(name="api", require_tenant=True)
server.add_middleware(AuthMiddleware(JWTAuth(secret="..."), tenant_claim="org"))
Serve it¶
→ DeploymentTest it without a network¶
Full pipeline (validation → guards → middleware → handler) in-process.
from promptise.mcp.server import TestClient
result = await TestClient(server).call_tool("search", {"query": "revenue"})
See also¶
- Quick Start — build your first agent in 5 minutes
- Guides — end-to-end, build-along tutorials
- Why Promptise — what ships and when to use it