Prompty is an asset class and format for LLM prompts
Project description
Prompty — Python Runtime
Prompty is a markdown file format (.prompty) for LLM
prompts. The Python runtime loads, renders, parses, and
executes these files. Every .prompty file becomes a typed
Prompty object.
Installation
# Core + Jinja2 renderer + OpenAI provider
pip install prompty[jinja2,openai]
# Core + Microsoft Foundry provider
pip install prompty[jinja2,foundry]
# Core + Anthropic provider
pip install prompty[jinja2,anthropic]
# Everything (all renderers, providers, OpenTelemetry)
pip install prompty[all]
Extras
| Extra | Packages | What it enables |
|---|---|---|
[openai] |
openai |
OpenAI provider |
[foundry] |
openai, azure-identity |
Microsoft Foundry provider |
[anthropic] |
anthropic |
Anthropic provider |
[jinja2] |
jinja2 |
Jinja2 template rendering |
[mustache] |
chevron |
Mustache template rendering |
[otel] |
opentelemetry-api |
OpenTelemetry tracing |
[all] |
All of the above | Everything |
Quick Start
1. Write a .prompty File
---
name: greeting
model:
id: gpt-4o-mini
provider: openai
connection:
kind: key
apiKey: ${env:OPENAI_API_KEY}
inputs:
- name: name
kind: string
default: World
template:
format:
kind: jinja2
parser:
kind: prompty
---
system:
You are a friendly assistant.
user:
Say hello to {{name}}.
2. Run It
import prompty
# One-shot: load + prepare + run
result = prompty.execute(
"greeting.prompty", inputs={"name": "Jane"}
)
print(result)
# Step-by-step
agent = prompty.load("greeting.prompty")
messages = prompty.prepare(
agent, inputs={"name": "Jane"}
)
result = prompty.run(agent, messages)
3. Async
result = await prompty.execute_async(
"greeting.prompty", inputs={"name": "Jane"}
)
API Reference
Core Functions
| Function | What it does |
|---|---|
load(path) |
Parse .prompty → Prompty |
render(agent, inputs) |
Template → rendered string |
parse(agent, rendered) |
Rendered string → list[Message] |
prepare(agent, inputs) |
Render + parse + threads → list[Message] |
run(agent, msgs) |
Executor + process → clean result |
process(agent, resp) |
Extract content → clean result |
execute(prompt, inputs) |
Full pipeline: load + prepare + run |
execute_agent(prompt, ...) |
Full pipeline with tool-call loop |
validate_inputs(...) |
Check required inputs present |
All functions have _async variants (e.g.,
execute_async, run_async, execute_agent_async).
Agent Mode (Tool Calling)
def get_weather(location: str) -> str:
return f"72°F and sunny in {location}"
result = prompty.execute_agent(
"my-agent.prompty",
inputs={"question": "Weather in Seattle?"},
tools={"get_weather": get_weather},
max_iterations=10, # default
)
The agent loop: calls the LLM, if it returns
tool_calls, executes the matching functions, sends
results back, repeats until the model returns a normal
response or max_iterations is exceeded.
Error handling:
- Bad JSON in tool arguments → error sent back to model for self-correction
- Tool exception → error string sent back to model
- Missing tool → error message sent back (no crash)
- Max iterations →
ValueErrorraised
Connection Registry
For pre-configured SDK clients or token-based auth:
# .prompty file — reference a named connection
model:
id: gpt-4o
provider: foundry
connection:
kind: reference
name: my-foundry
from openai import AzureOpenAI
from azure.identity import (
DefaultAzureCredential,
get_bearer_token_provider,
)
client = AzureOpenAI(
azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
azure_ad_token_provider=get_bearer_token_provider(
DefaultAzureCredential(),
"https://cognitiveservices.azure.com/.default",
),
)
prompty.register_connection("my-foundry", client=client)
# Now run — executor resolves the client by name
result = prompty.execute(
"my-prompt.prompty", inputs={...}
)
Structured Output
Define outputs in frontmatter to get
JSON-parsed results:
outputs:
- name: city
kind: string
description: The city name
- name: temperature
kind: integer
description: Temperature in Fahrenheit
The executor sends this as OpenAI's response_format
with json_schema, and the processor automatically
JSON-parses the result.
Streaming
agent = prompty.load("chat.prompty")
messages = prompty.prepare(
agent, inputs={"question": "Tell me a story"}
)
# Set stream option
agent.model.options.additionalProperties = {
"stream": True,
}
response = prompty.run(agent, messages, raw=True)
# response is a PromptyStream — iterate for chunks
for chunk in prompty.process(agent, response):
print(chunk, end="", flush=True)
Streaming handles tool call deltas (accumulated across chunks), refusal detection, and empty heartbeat chunks.
Tracing
from prompty import Tracer, PromptyTracer, trace
# Register a tracer
Tracer.add("console", prompty.console_tracer)
Tracer.add(
"json", PromptyTracer("./traces").tracer
)
# All pipeline functions automatically emit traces
result = prompty.execute(
"my-prompt.prompty", inputs={...}
)
# Custom functions
@trace
def my_function():
...
OpenTelemetry integration:
from prompty.tracing.otel import otel_tracer
Tracer.add("otel", otel_tracer())
.prompty File Format
Structure
---
# YAML frontmatter (Prompty schema)
---
# Markdown body (becomes `instructions`)
# Uses role markers and template syntax
Role Markers
system:
You are a helpful assistant.
user:
{{question}}
assistant:
I'd be happy to help.
Thread Inputs
Conversation history is passed via a kind: thread
input property:
inputs:
- name: conversation
kind: thread
Place {{conversation}} in the template where
thread messages should be injected:
system:
You are a helpful assistant.
{{conversation}}
user:
{{question}}
The caller passes a list of messages as the thread input value.
Variable References
| Syntax | Purpose |
|---|---|
${env:VAR} |
Env variable (required) |
${env:VAR:default} |
Env variable with fallback |
${file:path.json} |
Load file content |
Connection Kinds
| Kind | When to use |
|---|---|
key |
API key auth (self-contained) |
reference |
Pre-registered SDK client |
anonymous |
Endpoint only, no credentials |
Legacy Format Support
Prompty v1 .prompty files are automatically
migrated with deprecation warnings. Key changes:
model.configuration→model.connectionmodel.parameters→model.optionsinputs(dict format) →inputs(list of Property)inputSchema→inputsoutputSchema→outputstemplate: jinja2→ structuredtemplatewithformatandparser
Development
# Install for development
uv pip install -e ".[dev,all]"
# Unit tests (excludes integration by default)
uv run pytest tests/ -q
# Lint
uv run ruff check .
uv run ruff format --check .
# Integration tests (requires API keys in .env)
uv run pytest tests/integration/ -v -o "addopts="
License
See LICENSE in the repository root.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file prompty-2.0.0a4.tar.gz.
File metadata
- Download URL: prompty-2.0.0a4.tar.gz
- Upload date:
- Size: 217.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
62ad99606c196a2785fd969f016f2a0db21873bb5cfc4c99133e89331f22b775
|
|
| MD5 |
9b4e686b798237aed199e2abea33988c
|
|
| BLAKE2b-256 |
f192fa6de325ad26fddcd1bbfe7fa504b4c823540ea951a67b993c23c619f0ee
|
Provenance
The following attestation bundles were made for prompty-2.0.0a4.tar.gz:
Publisher:
prompty-python.yml on microsoft/prompty
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
prompty-2.0.0a4.tar.gz -
Subject digest:
62ad99606c196a2785fd969f016f2a0db21873bb5cfc4c99133e89331f22b775 - Sigstore transparency entry: 1245386075
- Sigstore integration time:
-
Permalink:
microsoft/prompty@89becf4677cd6025096bd3466568e236ffbd0cb5 -
Branch / Tag:
refs/tags/python/2.0.0a4 - Owner: https://github.com/microsoft
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
prompty-python.yml@89becf4677cd6025096bd3466568e236ffbd0cb5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file prompty-2.0.0a4-py3-none-any.whl.
File metadata
- Download URL: prompty-2.0.0a4-py3-none-any.whl
- Upload date:
- Size: 87.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9a2deedcf2570cf03148e0d0e1d3399fee4d58375852257a5a45b039378b0194
|
|
| MD5 |
f92616820bb28da962f80b2a05e12a41
|
|
| BLAKE2b-256 |
83bc812199c52373374c0fa56f9c0c674d9c7b52f728eeb8e926f626a9577e0a
|
Provenance
The following attestation bundles were made for prompty-2.0.0a4-py3-none-any.whl:
Publisher:
prompty-python.yml on microsoft/prompty
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
prompty-2.0.0a4-py3-none-any.whl -
Subject digest:
9a2deedcf2570cf03148e0d0e1d3399fee4d58375852257a5a45b039378b0194 - Sigstore transparency entry: 1245386081
- Sigstore integration time:
-
Permalink:
microsoft/prompty@89becf4677cd6025096bd3466568e236ffbd0cb5 -
Branch / Tag:
refs/tags/python/2.0.0a4 - Owner: https://github.com/microsoft
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
prompty-python.yml@89becf4677cd6025096bd3466568e236ffbd0cb5 -
Trigger Event:
push
-
Statement type: