Skip to main content

Psych Runtime

A Python library for running AI agents inside your application. It runs an agent's tool calls, saves a Run's progress as it goes, pauses for approval before the calls you choose, and records everything a Run did so you can read it back. You supply the model, the tools and the database.

psychruntime.com · Documentation · Browser demo · Changelog

gate PyPI Python 3.12+ Apache-2.0

Status: pre-alpha. The public API changes between minor releases, and every breaking change is in CHANGELOG.md before it ships. Names scheduled for removal warn for at least one minor release first. The PyPI badge above shows the current release.

What it looks like

One agent, one tool, offline. The test suite runs this file on every commit.

import asyncio
import psych_runtime
from psych_runtime.testing.fake_model import FakeModel


async def lookup_order(order_id: str) -> dict[str, str]:
    """Look up an order by its id."""
    return {"order_id": order_id, "status": "shipped"}


spec = psych_runtime.AgentSpec(
    name="support",
    instructions="Help the customer with their order.",
    model=psych_runtime.ModelRef(model="fake-standard"),
    tools=(psych_runtime.CodeTool(name="lookup_order"),),
)


async def main() -> None:
    model = (
        FakeModel()
        .turn(text="Checking.", tool_calls=[("lookup_order", {"order_id": "A1"})])
        .turn(text="A1 has shipped.")
    )
    async with psych_runtime.session(model, tools=[lookup_order]) as s:
        view = await s.ask(spec, "where is order A1?")
        print(view.text)  # A1 has shipped.

        report = await psych_runtime.report(s.store, view.run_id)
        print(report.totals.usage, report.totals.cost)


asyncio.run(main())
A1 has shipped.
input=0 output=0 cache_read=0 cache_write=0 cache_write_1h=0 reasoning=0 None

The tool ran: report.tool_calls says so, from the log. Cost is None because no price table was passed; it is never rounded to zero.

Run it

Python 3.12 or newer. The package depends on pydantic and httpx.

pip install psych-runtime
psych new demo && cd demo && python main.py

Expected:

No OPENAI_API_KEY set, so this run uses the fake model.

Order A1 has shipped with DHL.

completed | 1 turn, 1 tool call | 0 tokens | cost None

Set OPENAI_API_KEY and the same file calls a real provider. psych new writes a main.py you own; the command line never runs an agent for you.

  • The distribution is psych-runtime, the import is psych_runtime, the command is psych.
  • session() defaults to an in-memory store that dies with the process. Pass a PostgresStore, MySQLStore or DynamoDBStore for anything that must survive a restart.
  • Get started walks through the file above, then a real model, a second tool, and reading a Run back.

What it handles

Guide
Recover a run after a worker stops. Another worker claims the expired lease, replays the log and carries on. A call the dead worker left open is settled unknown, not re-run, unless the tool is registered safe_to_retry=True. Needs a durable store. Persist and recover runs
Require approval for selected tool calls. By name or by annotation. A matching call suspends the Run with its exact arguments and waits for a decision from any process. Approvals
Connect Python functions, HTTP endpoints, MCP servers and A2A agents as tools, resolved fresh every turn. Code tools, MCP
Inspect a run: status for a screen, the answer with its work, a report with tool calls, usage and cost, or the raw log. Every read takes a scope=. Reading a Run
Track token usage and cost per model call, split by cache state, with provider-versus-estimated provenance. Pricing
Serve multiple tenants from one process: a Scope on every record and every outbound call. Multi-tenancy

Where it runs

Psych is a dependency you import, not a service you deploy. Your request handler admits a Run and returns; a Worker in a process of yours claims it and executes it; the two share your database and nothing else.

Psych brings no HTTP server, auth, user model, scheduler, UI, prompt library, eval framework, vector store, budget enforcement or model router. Your application already has those, and a library that brought its own would argue with them. psych new api --template fastapi shows the split.

Limitations worth knowing before you build on it:

  • Only what you register is safe to retry. After a crash, a tool call recorded as started is settled unknown unless it was registered safe_to_retry=True. Psych does not make an external side effect repeatable; it refuses to guess.
  • A sandbox says what it proved, not what it hopes. Every backend grades ten guarantees per execution and reports the isolation level it actually reached; output produced under weaker terms than were requested is withheld rather than returned. A plain subprocess limits a program and does not isolate it, and it says so. Namespaces and containers reach a kernel boundary; no local backend reaches one on macOS or Windows, where a request for full isolation is refused instead of approximated.
  • Cost is only as good as its source. Cost.source distinguishes an amount returned by the provider from one estimated using the bundled, dated price snapshot or your override. A model with no known price records cost=None. Token totals carry their own usage_source; missing provider usage is never presented as a measured zero.
  • Provider support is the OpenAI-compatible chat API. One client reaches OpenAI and any gateway that speaks the same protocol; anything else is a ModelClient you implement.

The example console

git clone https://github.com/psych-systems/psych-runtime && cd psych-runtime
cp .env.example .env             # set PSYCH_POSTGRES_PASSWORD; compose refuses to start without it
docker compose up --build        # then http://localhost:3000

examples/playground/ is an application built on the library: publish an agent, talk to it, watch the log, read the report. It supplies the HTTP server and the UI Psych does not. It is an example, not a hardened service; do not put it on the public internet.

For coding agents

The repository ships 26 skills, one per feature, in .agents/skills/. Give your coding agent this instruction:

Read https://raw.githubusercontent.com/psych-systems/psych-runtime/main/.agents/skills/psych/SKILL.md
and follow it to add Psych to this project.

psych skills install copies them into a project.

Documentation

psychruntime.com/docs is generated from this repository: the API reference from psych_runtime.__all__, the guides from the skills above, the changelog and design notes copied verbatim. The build fails when any page disagrees with its source.

Contributing, support and security

  • CONTRIBUTING.md: what is welcome, how to set up, and what a change has to pass.
  • Issues for bugs and questions. Most bugs reproduce against the fake model with no provider and no network; a failing test beats a description.
  • SECURITY.md: report vulnerabilities privately through the advisory form, never as a public issue.

Development

uv sync --all-extras --group dev
scripts/dev-services.sh start        # real Postgres, MySQL and DynamoDB Local
scripts/check.sh                     # ruff, mypy --strict, import-linter, generated docs, three test layers

Licence

Apache-2.0. See LICENSE, and NOTICE for the one third-party attribution the package carries.

Metadata

Release files for psych-runtime 0.1.4

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

Source distribution (sdist)

Source distribution for psych-runtime 0.1.4
File Size Uploaded Provenance
psych_runtime-0.1.4.tar.gz 3.4 MB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for psych-runtime 0.1.4
File Interpreter ABI Platform
psych_runtime-0.1.4-py3-none-any.whl Python 3 none any Details

Total release size: 4.3 MB

Release files / psych_runtime-0.1.4.tar.gz

Download URL psych_runtime-0.1.4.tar.gz
Size 3.4 MB
Tags Source
SHA-256 checksum
How to use checksums
0097c49c0234cde0f52fbf78f77535f83847d7802323fdce15082872fb6bed3c
BLAKE2b-256 checksum
How to use checksums
c74db7ecfcee5382a848f3d42602015db535dee503f09fef64b68953c469bb76
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.

Transparency log

Release files / psych_runtime-0.1.4-py3-none-any.whl

Download URL psych_runtime-0.1.4-py3-none-any.whl
Size 934.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
eed92205156fb6e36163087cb78ff8734339e34786e7f54a6da2db5b88145c90
BLAKE2b-256 checksum
How to use checksums
83c49deffd777935a4153ba0c9b4755eb60022f17e8236188b250f1dc89c871e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.

Transparency log

Security for psych-runtime 0.1.4

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for psych_runtime-0.1.4.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.

Transparency log

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