Skip to main content

Prompty is an asset class and format for LLM prompts

Project description

Prompty — Python Runtime

PyPI Python 3.11+

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 .promptyPrompty
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 iterationsValueError raised

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.configurationmodel.connection
  • model.parametersmodel.options
  • inputs (dict format) → inputs (list of Property)
  • inputSchemainputs
  • outputSchemaoutputs
  • template: jinja2 → structured template with format and parser

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

prompty-2.0.0a6.tar.gz (237.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

prompty-2.0.0a6-py3-none-any.whl (99.9 kB view details)

Uploaded Python 3

File details

Details for the file prompty-2.0.0a6.tar.gz.

File metadata

  • Download URL: prompty-2.0.0a6.tar.gz
  • Upload date:
  • Size: 237.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for prompty-2.0.0a6.tar.gz
Algorithm Hash digest
SHA256 333170fe090a9cb1bec58100b229c657fc395c0447235b8095ea132611f750cb
MD5 4e2f9afade1ac3945c53ce3b91254925
BLAKE2b-256 1b934d39baa7fa4cd2e1aa8e542fce24c59402e1c5f4b636870b62b93a94ebd8

See more details on using hashes here.

Provenance

The following attestation bundles were made for prompty-2.0.0a6.tar.gz:

Publisher: prompty-python.yml on microsoft/prompty

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file prompty-2.0.0a6-py3-none-any.whl.

File metadata

  • Download URL: prompty-2.0.0a6-py3-none-any.whl
  • Upload date:
  • Size: 99.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for prompty-2.0.0a6-py3-none-any.whl
Algorithm Hash digest
SHA256 0d8c36d0d4ceda8dd1585f3143c920b765890f3c48a5d7a6f00a6c081a54d828
MD5 61ed822671df819d695608150a22132f
BLAKE2b-256 515903b210d4905d4daf05990745e327a5afd670204df30036b67f588a003f4e

See more details on using hashes here.

Provenance

The following attestation bundles were made for prompty-2.0.0a6-py3-none-any.whl:

Publisher: prompty-python.yml on microsoft/prompty

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page