Typed markdown documents backed by Pydantic models
Project description
Archetype
Type-safe markdown at every agent boundary.
Archetype gives you the tools — backed by Pydantic models — to validate data at agent boundaries and guide agent behavior. In agentic systems, structured data moves between agents as LLM-generated markdown — patient assessments, contract analyses, audit findings, software designs. Because this data is generated and non-deterministic, producers and consumers diverge silently: a required section gets dropped, a heading gets renamed, a field comes back in the wrong format. Nothing catches it, so the error propagates through the system.
Archetype makes the Pydantic model the contract at every agent boundary. At boundaries, it injects the markdown contract into agent instructions and validates markdown the agent generates. Inside agents, field descriptions from the model provide semantic context in prompts. One change to the Pydantic model propagates to every touchpoint of the corresponding markdown file.
Capabilities
| Capability | Description |
|---|---|
| Contract generation | Embed markdown contracts into any text an agent reads: instructions, prompts, skills, etc. |
| Markdown parsing and validation | Validate agent-generated markdown against the model — missing sections, misnamed fields, and type mismatches surface as errors you can prompt the agent to correct. |
| Annotation-driven layout | Declare how each field renders — as a heading, code block, list, or table — directly on the model. No separate template files or format strings. |
| Structural validation at class definition | Markdown modeling errors are caught at definition time, not mid-run. |
| Instance rendering | Render a populated model instance to well-formed markdown — no format strings, no templates to maintain. |
| Field descriptions as semantic context | Field descriptions flow from the model into agent instructions, giving agents the semantic context they need to reason correctly. |
Installation
pip install archetype-md
Quickstart
Given this model:
from typing import Annotated
from archetype.markdown import (
AsBulletList,
AsHeading,
MarkdownDocument,
MarkdownHeader,
TextTemplate,
generate_contract,
parse_markdown_as,
render_markdown,
)
class Finding(MarkdownHeader):
heading: Annotated[str, TextTemplate("Finding {ordinal} — {value}")]
recommendations: Annotated[list[str], AsBulletList()]
description: Annotated[str, AsHeading()]
class Review(MarkdownDocument):
heading: Annotated[str, TextTemplate("{value}")]
summary: Annotated[str, AsHeading()]
findings: list[Finding]
# Generate the markdown contract to embed in an agent instruction
contract = generate_contract(Review)
# Parse markdown back into a validated model instance
review = parse_markdown_as(produced_markdown, Review)
# Render a populated instance back to markdown
output = render_markdown(review)
A populated document — what render_markdown produces and parse_markdown_as consumes — looks like this:
# Q4 Code Review
## Summary
Two issues found, both fixable with minor changes.
## Findings
### Finding 1 — SQL Injection in login handler
- Use parameterised queries
- Validate all user input at the controller layer
#### Description
The login handler at auth.py:42 builds SQL by string concatenation,
allowing an attacker to inject arbitrary SQL.
### Finding 2 — Missing rate limit on password reset
- Add a rate limit of 5 requests per minute per IP
- Return a generic error message to avoid user enumeration
#### Description
The password reset endpoint accepts unlimited requests,
enabling brute-force and enumeration attacks.
Modules
archetype.markdown
Typed markdown documents backed by Pydantic models.
| Symbol | Purpose |
|---|---|
MarkdownDocument |
Base class for top-level documents (adds optional YAML frontmatter) |
MarkdownHeader |
Base class for heading-shaped sub-documents |
generate_contract(cls) |
Generate the markdown contract — annotated structure with placeholder comments and inline field descriptions |
render_markdown(obj) |
Render a populated instance to markdown |
parse_markdown_as(text, cls) |
Parse markdown and return a validated instance |
template_fields(cls) |
Return heading text and description for each heading-shaped field; non-heading fields are skipped |
extract_subtree(text, *, heading_level, title_match) |
Extract a uniquely named heading subtree and rebase it to level 1 |
Field annotations (attached via Annotated[T, ...]):
| Annotation | Field type | Renders as |
|---|---|---|
AsHeading() |
str |
Markdown heading section |
AsCodeBlock(language=...) |
str |
Fenced code block |
AsBulletList() |
list[str] |
Bullet list |
AsNumberedList() |
list[str] |
Numbered list |
AsTable() |
list[BaseModel] |
Markdown table |
TextTemplate("{value}") |
str (heading field) |
Formatted heading text |
archetype.templating
Jinja-based template resolution with markdown-aware globals.
from archetype.templating import resolve
instructions = resolve(
template_text,
feature=state.feature_definition,
)
resolve runs with strict undefined semantics — any missing variable raises jinja2.UndefinedError immediately. Two globals are available inside every template: template_fields(ModelClass) and generate_contract(ModelClass).
Design
The model is the contract. Annotations on fields drive all rendering and parsing behaviour. No separate config, no code generation — change the model, everything updates.
Strict by default. parse_markdown_as raises MarkdownValidationError with field-localized messages on any mismatch. resolve raises on undefined template paths. Silent partial results are not produced.
Development
pdm install
pdm run test
pdm run lint
pdm run check-format
pdm run typecheck
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 archetype_md-0.2.0.tar.gz.
File metadata
- Download URL: archetype_md-0.2.0.tar.gz
- Upload date:
- Size: 43.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
efff2e377b55119aff723d07317d4be30617fb9a1434fc15be993f2a508a4dc4
|
|
| MD5 |
eaeffb54455c30968438182e8a3f4836
|
|
| BLAKE2b-256 |
828bb82732104dbe1182b9a06c6aca944e3065957288a3dda361bfc504b3feed
|
Provenance
The following attestation bundles were made for archetype_md-0.2.0.tar.gz:
Publisher:
ci.yml on monkeynaut-ai/archetype
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
archetype_md-0.2.0.tar.gz -
Subject digest:
efff2e377b55119aff723d07317d4be30617fb9a1434fc15be993f2a508a4dc4 - Sigstore transparency entry: 1756802531
- Sigstore integration time:
-
Permalink:
monkeynaut-ai/archetype@230b635065dda9db4f214e4c15fed3956e3204b6 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/monkeynaut-ai
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@230b635065dda9db4f214e4c15fed3956e3204b6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file archetype_md-0.2.0-py3-none-any.whl.
File metadata
- Download URL: archetype_md-0.2.0-py3-none-any.whl
- Upload date:
- Size: 34.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d08036f49ab8b635e31602fe5767d4c4428519561e3802e49ccf31585a8b84a9
|
|
| MD5 |
cfe72e3914c55c83cdafa08374d2566e
|
|
| BLAKE2b-256 |
80a0ccd3211d9131d84b50593bc5d87183eb191a46c60857a02204887aadb41c
|
Provenance
The following attestation bundles were made for archetype_md-0.2.0-py3-none-any.whl:
Publisher:
ci.yml on monkeynaut-ai/archetype
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
archetype_md-0.2.0-py3-none-any.whl -
Subject digest:
d08036f49ab8b635e31602fe5767d4c4428519561e3802e49ccf31585a8b84a9 - Sigstore transparency entry: 1756802535
- Sigstore integration time:
-
Permalink:
monkeynaut-ai/archetype@230b635065dda9db4f214e4c15fed3956e3204b6 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/monkeynaut-ai
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@230b635065dda9db4f214e4c15fed3956e3204b6 -
Trigger Event:
push
-
Statement type: