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, 0.1.0. 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.

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, priced from a table you pass. 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.
  • The subprocess sandbox limits, it does not isolate. It sets rlimits and drops privileges, but shares the host filesystem, and its network denial is a self-report. The container sandbox is the one with kernel isolation.
  • Cost is only as good as the price table. A model with no known price records cost=None, and the report counts unpriced calls.
  • 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
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.

Download files

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

Source Distribution

psych_runtime-0.1.1.tar.gz (2.8 MB view details)

Uploaded Source

Built Distribution

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

psych_runtime-0.1.1-py3-none-any.whl (708.0 kB view details)

Uploaded Python 3

File details

Details for the file psych_runtime-0.1.1.tar.gz.

File metadata

  • Download URL: psych_runtime-0.1.1.tar.gz
  • Upload date:
  • Size: 2.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for psych_runtime-0.1.1.tar.gz
Algorithm Hash digest
SHA256 1c6b71bf4ab7edb49aa3e4d32b6dea083dba8d9456486b8f76eb8357c7df7ff9
MD5 e78bcfecefe7902790dcddcf54e991f8
BLAKE2b-256 0394812edbb6eceea6bdd2b20cf76e112b3e33d06858c9468a69173e614a6831

See more details on using hashes here.

Provenance

The following attestation bundles were made for psych_runtime-0.1.1.tar.gz:

Publisher: release.yml on psych-systems/psych-runtime

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

File details

Details for the file psych_runtime-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: psych_runtime-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 708.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for psych_runtime-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 3b473bb08f03b4676d914b4febb54e6c4e82eb76549e1f5525f4dbfbe5a9f8e2
MD5 72ef672e840484479540e416bfb022bd
BLAKE2b-256 a5ad2069fa99785541daabd8cf5d16c74b53f85c689cabda94495ee4839ff20f

See more details on using hashes here.

Provenance

The following attestation bundles were made for psych_runtime-0.1.1-py3-none-any.whl:

Publisher: release.yml on psych-systems/psych-runtime

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

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 files

0.1.0

2 files

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