Poia — from the Greek poíēsis (ποίησις): the bringing-forth of something into being. The name points at the process of creating, not the thing created.
A shared abstraction layer for thinking with AI — a means–ends workspace for bringing new approaches to new problems into being. Keep the big picture human-led, lean on structure and models where they help, and stay kind to attention.
- Introduction — the argument and the system (youtu.be/hJyp-ewotfY): the why behind Poia and a tour of the means–ends workspace. Narration in docs/SCRIPT.md.
- Product demo — a live walkthrough (youtu.be/N0_T6hOuiiE): Poia working a sample project end to end.
Most AI tools hand back a fixed answer — a block of prose you read top to bottom, the way you'd read a page in a book. Poia drops that form. The work lives in a typed graph instead of a chat transcript, and you steer it through judgment at the level of abstraction rather than by reading everything the model produces.
Every node is tagged by kind — an end (a goal worth reaching), a means (a step toward it), an assumption (a premise the work leans on), an observation (what reality returned), or an option (a choice still open). Ends and means nest, so the graph is a ladder of abstraction you can zoom in and out of.
Your sense-making and the agent's execution run side by side instead of in one scroll: you build and critique the structure while the agent writes code, runs it, and reports back. Nothing the agent produces changes the graph until you commit it — so judgment stays an explicit human act. And because the answer is structured rather than fixed, you can challenge any node and regenerate from there, instead of only reading it.
This project started from something that makes me sad, and even a little angry: many people now feel that as AI becomes more powerful, they are becoming replaceable. I understand the worry, but I do not think that conclusion follows.
My instinct, both as an engineer and as someone drawn to Kant, is to ask what assumptions make that fear feel so inevitable. I am especially drawn to Kant because he teaches us to ask not only whether a claim is true, but what frame, limits, and premises make that claim possible in the first place. I tried my best to be rigorous and fair: to ground my claims, where I can, in empirical research and careful reasoning, and not to make my private beliefs carry the argument. There is only one assumption I openly start from, because I think it should be common ground among human beings: the human is the end we build for. AI is a tool, however powerful.
This pursuit is definitely not finished, and I expect many parts of it to change. I welcome critique. My hope is that this project can help us feel a bit more empowered when working with AI — not by denying what AI can do, but by making clearer what should still belong to human judgment.
“Act in such a way that you treat humanity … never merely as a means to an end, but always at the same time as an end.” — Immanuel Kant, Groundwork of the Metaphysics of Morals (1785)
A person is not a statistical stand-in for “the user” — we are the source of value and creativity, so an assistant is better built around human judgment than trying to replace it. That assumption drives every design choice:
- Humans are good at creative leaps and connecting abstract dots, and slow when buried in fine-grained detail.
- LLMs are strong when the task has a clear boundary and the context is concise.
- We overload when flooded with detail at once; the antidote is to zoom in and out, a little new at a time.
Poia sits on that seam: you hold the shape of the problem, the model works bounded slices of it, and the graph keeps both honest. The full argument — and the cognitive science behind it — is in the narration script (docs/SCRIPT.md) and the design rationale (docs/DESIGN_RATIONALE.md).
What's in this repo — Poia the application itself:
poia/
├── src/ # the Next.js app: UI, routes + API, and all Poia logic
│ ├── app/ # routes (/web, /desktop) and the server API under app/api
│ ├── components/ # React UI (cockpit, conversation, agent, desktop shells)
│ └── lib/ # the engine: typed graph, agent loop, extraction, harness, retrieval
├── src-tauri/ # Rust/Tauri desktop wrapper — the same app in a native shell
├── e2e/ # Playwright end-to-end tests
├── public/ # static assets served at the web root
├── docs/ # design rationale, narration script, references, desktop setup
└── *.config.* # Next, TypeScript, ESLint, PostCSS, Playwright, Vitest config
Don't confuse this with the section below: this repository is the tool; the tree there is an example workspace you point Poia at, which lives in its own folder elsewhere and is not shipped here.
Poia operates on an ordinary project folder separate from this repository — you point it at a directory and it reads and writes files there through tools. The introduction demo runs on a small sample search-engine project (not shipped in this repo) laid out like any codebase:
your-workspace/
├── src/ # the project's source (reached by the agent at read time)
├── test/
├── web/
├── index.html
├── README.md
└── .poia/ # Poia's own state — created automatically in the workspace
├── graph.json # the canonical typed graph (ends/means/assumptions/observations)
└── history/v<N>/ # a versioned snapshot per graph write (file history)
Only .poia/ belongs to Poia; everything else is your code, untouched except through
explicit edits. The graph holds pointers and semantic concerns, not file copies —
so a node names a subsystem or invariant, and the files are fetched on demand. Deleting
.poia/ resets Poia's view of the workspace without affecting your project.
Early / experimental. Architecture and UX are still moving quickly, and automated test coverage is incomplete — expect rough edges. Good for trying the idea, not for production guarantees.
The graph stores semantic concerns (subsystems, capabilities, invariants, contracts), not a mirror of the file tree — the codebase is reached through tools at read time. For the "why" behind the design see docs/DESIGN_RATIONALE.md, the narrated argument in docs/SCRIPT.md, and the sources behind its claims in docs/REFERENCES.md.
Honest gaps surfaced by our own testing and demo recording — the idea works, but these edges are real:
- Graph persistence is best-effort. During a session the live in-browser graph is
the source of truth; writes to
.poia/graph.jsonare atomic but can lag, and a concurrent save may hit a409 (stale store version)and retry — so the on-disk graph can trail what you see. Reliable reproduction of a state currently means restoring a snapshot, not reloading from disk. - Server agent runs don't yet honor per-workspace command allowlists. The agent-run path doesn't thread your workspace config through, so command gating relies on the in-app approval prompt rather than a configured allowlist.
- Pruning works on plain prose. Deleting a span from an answer anchors only on plain paragraphs/lists; answers containing diagrams, tables, or headings may refuse the selection, and a prune can leave an orphaned heading behind.
- Blocking hand-offs depend on model behavior. Even with the rule that an explicit "your call" should pause for your decision, whether the agent surfaces a clean set of options varies from run to run.
- A commit can attach off-screen. An assumption or observation the agent commits may land on a node outside your current zoom, so its chip won't appear on the row you're looking at (the commit still happens).
- Agent output format can wobble. The agent occasionally returns prose without the structured summary; a backfill salvages most cases, but empty/malformed turns still happen.
- Incomplete automated test coverage — see Status above.
- Web UI: Next.js (App Router), React, TypeScript
- Desktop: Tauri wrapping the same app
- Structure view: a custom React outline (zoom in/out); the earlier spatial React-Flow canvas was retired
- Optional agent harness: LangGraph-style pipeline (see below)
Install dependencies, then run the dev server:
npm install
npm run devOpen http://localhost:3000/web for the web UI
(the root / redirects to /web).
/web— light cockpit (Poia in the browser)./desktop— Cursor-style dark shell for the Tauri desktop app (shared graph/agent logic, different chrome).
To enable the LLM features, add your Anthropic key to .env.local:
ANTHROPIC_API_KEY=sk-ant-...Requires Rust and a Tauri-supported OS. Windows setup (MSVC, PATH, troubleshooting): docs/DESKTOP_TAURI_SETUP.md.
npm run desktop:devRuns next dev (via dev:desktop: no auto-browser, bound to 127.0.0.1) and
opens the Tauri window at /desktop. desktop:build does not start a
website — it only compiles Next + Rust.
npm run desktop:buildNote:
src-tauri/tauri.conf.jsonmay have"bundle": { "active": false }while iterating without icon assets; addsrc-tauri/icons/*and setactive: truewhen you want installers.
Edit web routes under src/app/web and src/app/desktop; shared UI lives in
src/components.
Optional software build/debug harness (LangGraph context pipeline + long-turn message folding):
- Set
NEXT_PUBLIC_LANGGRAPH_HARNESS=1in.env.localto enable. - When off, the agent uses the previous behavior only.
This adds a bounded Poia slice + retrieval pack assembly step before each agent loop and optional conversation summarization between tool rounds.
npm run test
npm run test:e2e