Prerequisites
- Python 3.10+
- A Moxn account and API key (get one at moxn.dev)
- An LLM provider API key (Anthropic, OpenAI, or Google)
Installation
Install the Moxn SDK using pip:Your First Moxn Call
Here’s a complete example that fetches a prompt, creates a session, sends it to Claude, and logs the interaction:From Template to Provider Call
The code above follows the core Moxn pattern (see Core Concepts):| Step | What Happens |
|---|---|
| 1. Fetch template | Your prompt (messages, variables, config) is retrieved from Moxn |
| 2. Create session | Template + your session_data = a session ready to render |
| 3. Build invocation | to_anthropic_invocation() returns a plain Python dict |
| 4. Call provider | You pass the dict to the provider SDK with **invocation |
You Control the Payload
The invocation is just a dictionary—you can inspect, modify, or extend it:Understanding the Code
Let’s break down what’s happening:1. MoxnClient as Context Manager
2. Fetching Prompts
- Branch access (
branch_name): Gets the latest version, including uncommitted changes. Use for development. - Commit access (
commit_id): Gets an immutable snapshot. Use for production.
3. Creating Sessions
session_data is typically a Pydantic model generated by codegen.
The (prompt) session holds the message history - you can append additional messages or context, append an LLM response followed by additional user messages.
It maintains the conversation history for the session. Each telemetry loggign call will log the session independently.
4. Converting to Provider Format
to_*_invocation() methods return complete payloads you can unpack directly into provider SDKs. They include:
- Messages formatted for the provider
- Model configuration from your prompt
- Tools and structured output schemas (if configured)
5. Logging Telemetry
Using Code Generation
For type-safe session data, generate Pydantic models from your prompts:render() method transforms your typed data into strings for prompt injection. This example renders documents as XML—a format that works well for providing structured context to LLMs.
Then use it in your code:
The Render Pipeline
When you create a prompt session, your typed data transforms through several stages:How It Works
When you create a prompt session withsession_data, the SDK:
- Stores your typed model — The Pydantic instance you pass to
create_prompt_session() - Calls
render()at invocation time — When you callto_anthropic_invocation()(or other providers) - Substitutes variables by name — Each key in the rendered dict matches a
{{variable}}block in your prompt
- Session data: Your original typed model (enables re-rendering with different logic)
- Rendered input: The flattened strings that were injected into the prompt
Why Two Representations?The dual-representation pattern serves distinct purposes:
This separation enables:
| Representation | Type | Purpose |
|---|---|---|
| BaseModel (session data) | Pydantic model | Type-safe data structure with validation, rich types (datetime, nested objects, lists) |
| *Rendered (TypedDict) | dict[str, str] | Flat string values ready for template injection |
- Re-rendering: Change how data is formatted without changing the data itself
- Telemetry: Log the structured input separately from the rendered output
- Testing: Compare different rendering strategies using the same session data