Skip to main content

agentyper

Agent-first Python CLI library — built on argparse + pydantic, Typer-compatible.

Typer was built for the era when type hints changed Python.
agentyper is built for the era when AI agents changed how software is operated.

Why Agentyper?

Typer was built for humans. Agents need something different.

Typer revolutionized CLI development by elegantly using type hints. However, because it is built on Click and Rich, it is fundamentally optimized for human eyeballs. When interacting with standard CLIs, AI Agents struggle: they cannot organically discover the tool's schema, they get blocked by interactive prompts ([y/N]), they hallucinate when parsing ANSI-colored tables, and they fail to self-correct when errors are returned as flat strings.

Agentyper keeps the beloved Developer Experience (DX) of Typer but replaces the execution engine with argparse and Pydantic. With a one-line switch (import agentyper as typer), your CLI instantly yields OpenAPI/JSON schemas, strict Pydantic structured errors, and deterministic programmatic overrides for interactive features.

📖 Learn more in our docs:

agentyper implements the CLI Agent Spec — a formal specification for agent-ergonomic CLI tools.

Install

pip install agentyper

Quick Start

Absolute minimum:

Create a main.py:

def main(name: str):
    print(f"Hello {name}")

Run it without importing anything:

agentyper main.py run Camila

Single function (like typer.run()):

import agentyper

def search(ticker: str, limit: int = 10):
    """Search securities by ticker."""
    results = service.search(ticker, limit)
    agentyper.output(results)   # routes via --format automatically

agentyper.run(search)

Multi-command app:

import agentyper

app = agentyper.Agentyper(name="my-tool", version="1.0.0")

@app.command()
def search(ticker: str, limit: int = agentyper.Option(10, help="Max results")):
    """Search securities."""
    agentyper.output(service.search(ticker, limit))

@app.command()
def delete(name: str):
    """Delete a record."""
    if agentyper.confirm(f"Delete '{name}'?"):
        service.delete(name)

app()

Typer migration — one line:

# import typer          ← before
import agentyper as typer  # ← after; everything else stays identical

What Agents Get for Free

Every parser gets the core machine-facing flags:

my-tool --schema                  # full JSON Schema of the entire app
my-tool search --schema           # JSON Schema for this command's params
my-tool search AAPL --format csv  # 4× cheaper output than table
my-tool search AAPL --format json # structured JSON output

Interaction flags are always accepted, but they are shown in --help only when the app or command declares them explicitly or when agentyper can tell they are relevant. Timeout remains capability-based:

my-tool delete alice --yes        # skip confirm() in agent mode
my-tool wizard --answers '{"confirms":[true],"prompts":["Alice","admin"]}'
my-tool sync --timeout 5000       # available when timeout support is enabled

This keeps --help output compact for simple non-interactive CLIs while still letting callers pass prompt-bypass flags defensively.

If you are an agent consuming an agentyper CLI, read docs/for-agents.md for schema discovery, error handling, and the full flag reference.
If you are building a CLI with agentyper, read docs/for-developers.md for patterns, best practices, and a pre-ship checklist.

Batch Execution (exec)

Every agentyper app ships a built-in exec command that reads a JSONL stream from stdin and dispatches each line to the appropriate subcommand in-process:

cat commands.jsonl | my-tool exec

Each line is a JSON object:

{"_cmd": "account.create", "name": "Assets:Bank", "open_date": "2024-01-01"}
{"_cmd": "transaction.add", "_opts": {"draft": true}, "date": "2024-01-15"}
Field Meaning
_cmd Dot-separated subcommand path ("account.create" → account create)
_opts Per-line flag overrides ({"draft": true} → --draft)
everything else Mapped to positional or flag args based on the command's signature

Each line emits one JSON result to stdout:

{"ok": true,  "exit_code": 0, "line": 1, "cmd": "account.create", "result": {...}}
{"ok": false, "exit_code": 2, "line": 2, "cmd": "transaction.add", "error": "..."}

Global flag forwarding

Any unrecognised flag passed to exec is forwarded verbatim to every dispatched command:

cat commands.jsonl | my-tool exec --target ledger.beancount

All commands in the batch must accept the forwarded flag; a command that does not will fail with exit code 2. Use per-line _opts for flags that apply only to some commands — they take precedence over forwarded flags when the same key appears in both.

Exec-owned flags

Flag Behaviour
--dry-run Injected into mutating commands only; non-mutating commands are unaffected
--ignore-errors Continue processing after a line error instead of stopping

Agent Ergonomics

Feature agentyper Typer
--schema on every command ✅ automatic ❌ manual
--format json/csv/table ✅ automatic ❌ manual
Structured JSON errors ✅ automatic ❌ free text
Exit code taxonomy (0/1/2) ✅ ❌ 0 or 1
Interactive features in agent mode ✅ bypass flags when interactive ❌ blocks
isatty() auto-format detection ✅ ❌
Dependencies argparse + pydantic Click + Typer

Typer Compatibility Matrix

agentyper implements Typer's core API. For most CLIs, import agentyper as typer works flawlessly. Because it is built from scratch on argparse + Pydantic (for LLM reliability) instead of Click, there are some differences.

Feature / API Status Notes
@app.command(), @app.callback() ✅ Supported Core app routing works identically.
Option(), Argument() ✅ Supported Core args mapping (default, help, etc.)
Type Hint Extraction ✅ Supported Uses Pydantic for robust validation.
Interactive Prompts (confirm()) ✅ Supported Enhanced with non-blocking agent overrides.
typer.Context (ctx) ✅ Supported Invocation-scoped context exposes ctx.format, ctx.runtime, ctx.root, ctx.params, and ctx.obj. click-specific methods (ctx.forward(), ctx.meta) still do not exist.
click Parameter Types ❌ Unsupported Fully replaced by Pydantic. Use Literal["A"] instead of click.Choice.
typer.style(), colors ❌ Unsupported Removed. Agents prefer plain text or structured JSON.
Custom Click logic ❌ Unsupported Executed purely via standard argparse.

Exit Codes

agentyper.EXIT_SUCCESS    = 0  # success
agentyper.EXIT_VALIDATION = 1  # bad input — agent should retry with correction
agentyper.EXIT_SYSTEM     = 2  # system error — agent should abort

Interactive Features

All interactive features from Typer work identically in a terminal. In agent/non-TTY mode, they resolve without blocking. The interaction flags may be hidden from --help on non-interactive commands, but they are still accepted by the parser:

# Human terminal: asks interactively
my-tool delete alice

# Agent: auto-confirm via flag
my-tool delete alice --yes

# Agent: pre-supply all answers
my-tool wizard --answers '{"confirms":[true,false],"prompts":["Alice","admin"]}'

# Agent: pipe answers from stdin
echo '{"confirms":[true]}' | my-tool delete alice --answers -

If static detection is not enough for your app shape, expose the flags explicitly:

app = agentyper.Agentyper(name="my-tool", interactive=True)


@app.command(interactive=True)
def wizard() -> None:
    ...

Timeout Support

--timeout MS is also opt-in. It appears when timeout support is declared at the app or command level.

app = agentyper.Agentyper(name="my-tool", default_timeout_ms=30_000)


@app.command(timeout_ms=5_000)
def sync() -> None:
    ...

Use enable_timeout=True if you want the flag available even when the timeout value is supplied elsewhere.

Invocation Context

Commands and callbacks can accept ctx: agentyper.Context to inspect the resolved invocation state:

@app.command()
def sync(ctx: agentyper.Context, target: str):
    client = build_client(ctx)
    agentyper.output({"target": target, "format": ctx.format})

Use this rule of thumb:

  • Pass ctx explicitly when the function is part of the command flow and invocation state is an important dependency.
  • Call agentyper.get_current_context() in deep helper code that needs invocation-scoped state without forcing ctx through unrelated layers.
  • If helper code may run outside an active CLI invocation, either accept ctx explicitly or handle the RuntimeError raised by get_current_context().

agentyper.Context exposes:

  • ctx.runtime for resolved framework state such as format, verbosity, answers, and timeout.
  • ctx.params for parsed command parameters.
  • ctx.root for resolved global/root flags.
  • ctx.obj for app-owned mutable shared state.

Helper code can also read the active invocation context without manually threading it through every call:

def build_client(ctx: agentyper.Context | None = None) -> Client:
    ctx = ctx or agentyper.get_current_context()
    return Client(timeout_ms=ctx.runtime.timeout_ms, verbose=ctx.runtime.verbosity > 0)

This hybrid pattern works well for reusable helpers and tests:

def emit_success(
    payload: dict,
    ctx: agentyper.Context | None = None,
) -> None:
    ctx = ctx or agentyper.get_current_context()
    agentyper.output(payload, format_=ctx.format_)


@app.command()
def run(ctx: agentyper.Context) -> None:
    emit_success({"status": "ok"}, ctx=ctx)

License

MIT

Metadata

Release files for agentyper 0.1.21

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for agentyper 0.1.21
File Size Uploaded Provenance Actions
agentyper-0.1.21.tar.gz 51.7 kB Without provenance Details for agentyper-0.1.21.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for agentyper 0.1.21
File Interpreter ABI Platform Actions
agentyper-0.1.21-py3-none-any.whl Python 3 none any Details for agentyper-0.1.21-py3-none-any.whl

Total release size: 98.0 kB

Release files / agentyper-0.1.21.tar.gz

Download URL agentyper-0.1.21.tar.gz
Size 51.7 kB
Tags Source
SHA-256 checksum
How to use checksums
7f5ac3d5e9dbc660ca64dc48a01f06b8d5ce76cecf284327c10ee7666b28db04
BLAKE2b-256 checksum
How to use checksums
b20902767eeb26a3293a70f4157e86ef9cf21a89e235e0d492b09e2bd26e1162
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.20 {"installer":{"name":"uv","version":"0.12.20","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / agentyper-0.1.21-py3-none-any.whl

Download URL agentyper-0.1.21-py3-none-any.whl
Size 46.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
bfe6aec457407979271e64e017110c0f3079af1640ddd52b27262b590644608d
BLAKE2b-256 checksum
How to use checksums
8c1c9876562c19eb54ff44ef659ecb5b2d76f12e454a6d50e8ceaefafed0a548
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.20 {"installer":{"name":"uv","version":"0.12.20","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for agentyper 0.1.21

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page