Psych Runtime
Reference

Ports

The interfaces you implement. Psych Runtime calls back only through these.

Store

protocol

class Store(*args, **kwargs)

Persistence, as narrow as an append-only log can be.

Every method here is expressible as one conditional write or one bounded read. An implementation that needs a transaction to satisfy this contract has misread it.

BlobStore

protocol

class BlobStore(*args, **kwargs)

Content-addressable-by-caller storage for payloads too large for a log record, put/get/delete by BlobKey, with range reads.

Every method is one operation against one object: no listing, no versioning, no multipart upload management exposed to a caller. The three adapters (psych_runtime.store.blob_memory, psych_runtime.store.blob_fs, psych_runtime.store.blob_s3) all pass psych_runtime.store.blob_contract, the same discipline psych_runtime.store.contract applies to Store.

MemoryStore

protocol

class MemoryStore(*args, **kwargs)

Durable facts across Runs, isolated by tenant and end user.

Not conversation history (that is the log) and not semantic retrieval (that is explicitly refused; DESIGN.md §15 and this package's README). A MemoryStore is a flat, small collection of facts per end user, recalled in full every time: there is no ranking, no similarity search and no partial retrieval, because those are exactly the features that would make this module the RAG framework Psych refuses to own.

ModelClient

protocol

class ModelClient(*args, **kwargs)

What Psych needs from a model provider.

One method. Everything else Psych does with models, it does itself.

Policy

protocol

class Policy(*args, **kwargs)

Authorization, implemented by the consumer against their own identity system.

Psych calls this; it never decides. An implementation that raises is treated as a denial rather than as a crash, because an authorization system being down should stop work rather than let it through, and should not take the Run's whole log with it.

SecretResolver

protocol

class SecretResolver(*args, **kwargs)

Resolves a credential name to a value, for exactly the Scope asking.

An implementation should resolve fresh, or from its own short-lived cache, rather than memoising forever: DESIGN.md §10.2's "fresh at every turn boundary" rule for tools applies here too, since a credential a consumer just revoked must stop working on the next resolve rather than the next process restart.

Telemetry

protocol

class Telemetry(*args, **kwargs)

The root of the tree. Every Run's telemetry starts here.

An implementation must never let a failure of its own escape into the caller: wrap an untrusted implementation in GuardedTelemetry rather than relying on callers to guard themselves.

Sandbox

protocol

class Sandbox(*args, **kwargs)

Runs one model-written program in isolation and reports the result.

DESIGN.md §18 rejects in-process execution outright: no implementation of this port may run the program in the calling process. Process isolation (psych_runtime.sandbox.subprocess) is the floor; a container (psych_runtime.sandbox.container) is available for consumers who need more.

PriceResolver

protocol

class PriceResolver(*args, **kwargs)

Price resolution is a port, not a hardcoded table.

DESIGN.md §13.2: the shipped table is a convenience with a known staleness problem. A consumer reconciling against their real provider bill supplies their own, and theirs is authoritative.

An implementation returns None for a model it does not know. It must not invent a rate, and it must not return zeros: compute_cost turns None into a recorded cost=None, which is the honest answer.

EgressPolicy

protocol

class EgressPolicy(*args, **kwargs)

Decides whether one outbound request may proceed.

Called once per request, with enough context for a real decision: which tenant is asking, and where the request is headed. The seam calls this before opening the connection, not after, so a denial never touches the network.

An implementation should be fast and free of side effects: it runs on every outbound call Psych makes, including the read side of a streamed model response, so anything slow here is a latency tax on everything.

On this page