Skip to main content
neosian

neosian

PyPI Docs CI License: Apache-2.0 Python 3.12 | 3.13 | 3.14

The state layer for LLM agents: durable conversations, agent-curated memory, skills, a shared board and a ledger of who did what, on storage you own (a directory, your Postgres, or one small state process), for the agent you already use or the one you build.

Two doors, one store:

  • Give your agent state. Claude Code, Codex, OpenCode, Muse Code, Pi or interactive Cursor get memory and skills over MCP and every session recorded through hooks: neosian setup --write lets you select the clients to connect, once per machine; neosian status says whether the machine is set up; the Python shell's bare neosian opens a chat with an agent that knows neosian, on the same memory, and runs the shell's verbs for you: ask it whether the machine is set up.
  • Build an agent. An async-only, stateless Agent (tools, streaming, fallback, guardrails, structured output) that a Conversation wraps into a durable, memory-bearing thread.

A headless Claude Code session lands as a recorded turn; neosian audit names it
The next Claude Code session opens on where we left off; neosian search finds the turn by its words

Set up once per machine, every session lands in the ledger: the Python shell's neosian audit names the turn, the next session opens on where we left off, and neosian search finds it by its words.

Agents read this repository too: llms.txt is the machine front door, neosian docs prints the shipped docs pages from the wheel (version-true), and every shell verb has --json and exit tiers — one CLI for humans and agents (neosian docs cli).

store = FileStore(home())                          # ~/.neosian, or your PostgresStore(dsn)
convo = Conversation(config, store=store, conversation_id="thread-829",
                     memory_scope=project_scope())  # user:<login>/proj:<dir>
response = await convo.send("Where did we leave off?")

Install

For an existing agent, install the native binary on macOS or Linux:

curl -fsS https://neosian.com/install | sh
neosian setup --write

The installer selects the platform, verifies the archive's SHA-256 and installs under ~/.neosian/bin, with a link in ~/.local/bin when that name is free. An existing Python command is preserved; neosian status names competing executables. In that case, run ~/.neosian/bin/neosian setup --write to connect the binary. Both implementations use the same home, with no data migration. Windows has a PowerShell installer and MSI on the GitHub Release. Publisher signing and Apple notarization are deferred; browser downloads can trigger macOS or Windows security warnings.

The binary's package-manager commands are npm install -g neosian and cargo install neosian --locked. Homebrew distribution is deferred. Cargo builds from source and requires the Rust version named by the crate. Use the original package manager to update these installations.

For the Python shell, including chat, the TUI, playground and eval, use uv tool install "neosian==1.12.1", or curl -fsS https://neosian.com/install | sh -s -- --python. For the SDK, use uv add "neosian==1.12.1". Python requires >= 3.12. The Python package includes its provider SDKs, MCP server and client, state process and OpenTelemetry spans, about 70 MB on disk, loaded on use. Model.FAKE and FileStore need no account. The one extra is the Postgres driver, uv add "neosian[postgres]==1.12.1"; [all] is its alias.

To work on neosian itself, uv sync --all-groups then uv run neosian version (the Development section has the gates).

One store under many agents

neosian setup --write asks which installed clients to connect to the home. The Python shell and Rust binary both provide setup, status, configure, update, mcp install, and record install over the same home. Status names competing neosian executables on PATH. Setup registers the executable running it; --binary PATH selects an explicit binary. No home migration is needed. Use --write --yes for all detected clients in scripts, or repeated --client C for an explicit selection. Setup and status accept --at CLIENT=DIR for a custom client configuration directory, for one run. Their hooks record each session into one store, so any of them picks up where another stopped: say "continue" and the agent receives that conversation in one call, with the note the last one left on departure; one ledger names them all, and which continued which.

Claude Code records a deployment fact; Codex recalls it from the same neosian store in a new session; one audit names both
Claude Code saves a project memory through MCP; the memory index lists it and neosian memory view shows the saved markdown file

Claude Code records the work, Codex picks it up, one audit names both. A memory write becomes a plain markdown document you can read, version and revert.

Build an agent

Keyless boot is an invariant: Model.FAKE is always available, so an install verifies with no account. The fake is scripted through the client_factory seam — the same seam the unit tier and the eval baseline use:

import asyncio

from neosian import Agent, AgentConfig, Message, Model, Role
from neosian.fake import FakeClient, FakeScript, FakeTurn

fake = FakeClient(FakeScript(turns=(FakeTurn(content="hello from the fake"),)))
config = AgentConfig(system_prompt="Be concise.", model=Model.FAKE,
                     client_factory=lambda _: fake)


async def main() -> None:
    response = await Agent(config=config).run(
        [Message(role=Role.USER, content="hello")], stream=False
    )
    print(response.message.content)


asyncio.run(main())

Set a key and name a real model (model=Model.CLAUDE_SONNET_5_5, the providers table below); tools are decorated functions whose signature is the schema (neosian docs tools). examples/ has one runnable file per feature, every one importing keylessly.

Durable messages and reminders

See neosian docs messaging for the shared messages tool, conversation and scope destinations, history annotations, explicit acknowledgment and claims. Reminders can be snoozed with a finding and a new due time on the same ID. Native conversations opt in with mailbox=MailboxConfig() from neosian.messaging. Regenerate client adapters after upgrading for automatic delivery. Pi and OpenCode also support wake requests while attached.

What is in the box

Each line is one page in the wheel — neosian docs <topic>.

  • Conversation and memory (memory). History is an append-only log; log-projection compaction pages aged turns out of context, search_history finds any turn by its words and recall_turn re-hydrates it verbatim — paging, not deletion. The one eraser is an operator's: neosian redact blanks recorded turns with the skeleton kept, neosian prune is retention on top. Memory is file-school: small markdown documents with frontmatter under mounted scopes, read and written through one memory tool (view, create, str_replace, insert, delete, rename); reflection at the close distills the session into deliberate writes. Every write is a full-content version row with an actor; a memory_write frame on the stream carries {command, path, version} so a host renders "remembered X" with a working revert_memory undo.
  • The shell and the ledger (cli). The six memory commands, the gardener (maintain), the operator verbs (versions, redact, revert), audit — what was done, by whom, when, on any substrate — search — the turns holding every term, newest first — export/import, which move a store whole, history included, and redact/prune, the turn eraser and the retention cutoff.
  • Skills (skills). A skill is a document under skills/<name> in a mount: versioned, curated by the mount flag, loaded by list_skills/load_skill, served over MCP as a prompt (a slash command in Claude Code).
  • MCP, both directions (mcp). python -m neosian.mcp serves the store to any client over stdio; McpServer.stdio/http/in_process consumes any MCP server as agent tools — schema verbatim, is_error in-band, the approval gate and hooks unchanged.
  • The agent you already use (agents). neosian record install spells the hooks that land a prompt-to-stop span as one turn by claude-code:<session> (Codex, OpenCode, Muse Code, Pi and interactive Cursor too), plus a sessions document; SessionStart prints the index, the pending handoff note and "where we left off" into the next window (OpenCode reads them from the server's instructions). A handoff is declared, never assumed: handoff writes the note on departure, continue_session carries a session on in one call, and the ledger shows which continued which. Registered once per machine, every project gets its own scope with no file of its own. A neosian Conversation on the same home shares the scope, so one audit names both.
  • The state process (topology). neosian serve puts memory and conversations on a port. The container runs the Rust binary over FileStore; the Python server also serves Postgres. RemoteStore drops in where FileStore does, core install. Bearer tokens env-only, per-client when you want the ledger to know who wrote.
  • The agent core (agent, tools). run(stream=True) yields eleven frozen AgentEvent dataclasses a host relays over SSE; AgentHooks observe every turn, call and tool; ToolGateConfig routes every tool call through one approver, and no decision is a denial; capability- aware fallback, guardrails on any model, structured output, prompt caching, multimodal blocks on Anthropic.
  • Under your own agent (interop). tool_definition(tool) is the definition any neosian tool sends to the model and the tool itself the executor, so the memory tool runs under a pydantic-ai or OpenAI Agents SDK agent (two runnable examples, keyless in the unit tier) or over MCP from any language; the data stays a directory you can grep, git and leave with.
  • Your own store (stores). The two storage ABCs and their constraints in plain words, the shipped conformance kits as the certification standard, and examples/sqlite_store.py, a third substrate that passes both kits and stays community custody.

Providers

API keys are read from environment variables; a provider is available when its key is set (asking for an unavailable model raises MissingAPIKeyError). For the shell, neosian configure stores any of them under the home and loads them where the environment has none.

Provider Env var Models
A registered door the door's api_key_env The day-one door for any model neosian has not shipped: any OpenAI-compatible endpoint via register_model (neosian docs quickstart)
Local (llama.cpp, Ollama) none: api_key_env=None A door that signs nothing, on a zero card; neosian chat finds a running llama-server or Ollama by itself and defaults to its model; the recipes and the measured local row (neosian docs local)
OpenAI OPENAI_API_KEY gpt-6.1-sol (latest), gpt-6-sol (default during migration), gpt-6-astra, gpt-6-luna; gpt-5.1 is superseded, on the Responses API with reasoning carried through tool loops and nothing stored at the provider
Anthropic ANTHROPIC_API_KEY claude-fable-5-1, claude-opus-5-5, claude-sonnet-5-5 (latest; chat default with no local server running), claude-sonnet-5 (library default during migration), claude-haiku-5-5 (the fast row, priced by prompt length); vision/PDF input, prompt caching, adaptive thinking
Cerebras CEREBRAS_API_KEY Default provider: gpt-oss-120b, qwen-3.8-27b
xAI XAI_API_KEY grok-4.6 — a shipped door row (Model.GROK_4_6), on the Responses API
Google Gemini API GEMINI_API_KEY gemini-3.8-flash, gemini-3.7-flash on the OpenAI-compatible endpoint (Model.GEMINI_3_8_FLASH; the introductory card through 2026-12-31)
Moonshot MOONSHOT_API_KEY kimi-k3: a shipped door row (Model.KIMI_K3), always reasoning
Alibaba Model Studio (Singapore) DASHSCOPE_API_KEY qwen3.8-max: a shipped door row (Model.QWEN_3_8_MAX); thinking on when a reasoning_effort is asked
Fake — Keyless, deterministic, always available (Model.FAKE)

Every shipped row is a Model member and answers to its wire id too (AgentConfig(model="gpt-6.1-sol")); each carries its provider's lifecycle as data (Model.X.spec.retires, card_until) and is earned by green dispatched runs of the memory baselines — membership is measured, never assumed (neosian docs baselines).

Storage

MemoryStore and ConversationStore are the contracts: async ABCs that own no connection, commit no transaction, issue no DDL. FileStore (a plain directory), PostgresStore (the postgres extra; schema by python -m neosian.schemas postgres | psql "$DSN") and RemoteStore (the state process's wire) implement both; a host may implement its own, kept honest by the shipped MemoryStoreContract / ConversationStoreContract conformance kits (neosian docs stores: the contract, the kits, a worked SQLite example that passes both). FileStore coordinates cooperating local processes through a root lock; restart all writers when upgrading. Network filesystems are outside this guarantee. Postgres supports distributed workers (neosian docs topology).

Evaluation

neosian eval suite.yaml runs YAML suites and exits nonzero on failure — an agent suite over variants × models × cases, and kind: memory, which scores store truth across scripted sessions on every transport. A suite names its agent file relative to itself, so it runs from any directory; --json prints the artifact and --output DIR places it. The shipped memory pack is all-green on models: [fake], and the same pack against the real providers produces the baselines page, fingerprint-gated so a prompt change without a recorded re-run fails make test.

Stability

v1.0.0 carries the API stability promise: Agent, Conversation, MemoryStore, and the neosian.evaluation facade stable under SemVer, the ecosystem seams (scope grammar, token classes, integer micro-USD, event vocabulary, error codes) SemVer-guaranteed, with a seam break only at a major, and the state process's wire (the twenty-one /v1/ routes and their envelope, neosian docs wire, versioned by WIRE_VERSION) stable under the same promise: one promise covering library, seams, and wire. Error codes are append-only forever. Consumers pin a release (neosian==X.Y.Z), never master. Model membership follows a rolling 30-day policy, independently of the stable library interfaces: ModelSelector offers per-tier DEFAULT and LATEST, while Model pins a concrete ID. A qualified replacement becomes latest when neosian ships it; default promotion and predecessor removal happen in the first release at least 30 days later. Each successor gets its own window, with visible migration warnings. Package upgrades change the catalog; the wall clock never changes an installed package's routing. Provider shutdowns can make an endpoint unavailable sooner. See neosian docs agent for selectors, exact pins and the policy.

Development

make install    # uv sync --locked --all-groups
make lint       # ruff + black --check + import-linter
make typecheck  # mypy --strict neosian tests examples
make test       # unit tier — the default gate, zero API keys
make size       # file-size gate (warn 300 / fail 500)
make test-external provider=anthropic file=~/path/to/creds  # real API calls
make test-postgres                                      # needs NEOSIAN_TEST_POSTGRES_DSN
make test-container                                     # both kits vs the container (docker)

The default gate needs no accounts; external tiers inject credentials value-blind. Sign off every commit (git commit -s): contributions are accepted under the Developer Certificate of Origin and licensed as the project is, Apache-2.0 — there is no CLA. Open an issue before a feature or a departure from documented behaviour; the public API is pinned by tests/unit/test_init.py, so an export change is a reviewed diff. SECURITY.md is where vulnerabilities go, never an issue.

Documents

  • neosian docs <topic> — the shipped pages, from the wheel: quickstart, memory, skills, messaging (messages and reminders), stores (author and certify your own store), agents, cli, mcp, interop (memory under pydantic-ai or the Agents SDK), agent, tools, local (llama.cpp and Ollama on the door), topology, wire (the state process's HTTP contract), baselines (the published per-provider memory numbers); the same pages online at neosian.com/docs, rendered from the wheel at the current release.
  • SERVICES.md — every env key and what turning it off means.
  • CHANGELOG.md — Keep a Changelog, one section per release.
  • SECURITY.md — where to report, and the supported line.
  • llms.txt — the machine-readable front door (byte-identical twin ships in the wheel).

Be kind and constructive in every project space; the maintainers read community@neosian.com.

Metadata

Release files for neosian 1.12.1

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

Source distribution (sdist)

Source distribution for neosian 1.12.1
File Size Uploaded Provenance
neosian-1.12.1.tar.gz 1.4 MB Without provenance Details

Built distribution (wheel)

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

Total release size: 2.2 MB

Release files / neosian-1.12.1.tar.gz

Download URL neosian-1.12.1.tar.gz
Size 1.4 MB
Tags Source
SHA-256 checksum
How to use checksums
749c6e6d6425a3bda6001fdbbf0e7ca699c792817fc960c07077a6f614a9b439
BLAKE2b-256 checksum
How to use checksums
3d5cd8b9569730d6223ddeea086e054c1ac17f309786a66581cf7ca699ef6524
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","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 / neosian-1.12.1-py3-none-any.whl

Download URL neosian-1.12.1-py3-none-any.whl
Size 804.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d483782cf884158a05f51b2e71cffe805162168695afbc6148ce1bfa88b2580e
BLAKE2b-256 checksum
How to use checksums
885aa02d134b464f8faffa60c49ca7b3c041cd25959fae44db16e248135b9d8f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","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 neosian 1.12.1

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.

Release history Release notifications | RSS feed

This release

1.12.1 This release

2 release files No provenance

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