vccs
Composable charting components for Vue 3, ported from Recharts
Operational Database For AI Agents. Open source. Self-host free or managed cloud.
DataPython · TypeScriptGitHub @ZIZKA-AI-SLOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Audit trail database for AI agents. Tamper-evident, checksum-backed decision logs with session replay and time-travel debugging to support EU AI Act Article 12 record-keeping. Drift detection, MCP, Python & TypeScript SDKs. Self-host or cloud.
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
When your agent misbehaves, see why.
Self-hosted audit trail for AI agents — one command or one dashboard click from any step back to root cause.
This repository is the open-source self-host stack (API, tenant dashboard, SDKs, MCP). Operator admin console and VPC deploy live in private zizkadb-cloud — see docs/REPO_SPLIT.md.
Requires Docker. First image pull may take 5–10 minutes.
Run again anytime: pip install zizkadb-sdk && zizkadb demo
Every agent team asks: Why did it say that? Why did it call that tool?Read the full README ↗Every agent decision linked to its cause. Causal agent memory, a tamper-evident audit log and time-travel debugging, in one open-source database on Postgres. Built for EU AI Act Article 12 record-keeping.
Keyword + vector search · Drift detection · MCP server · Python & TypeScript SDKs · Self-host or cloud
Quickstart · Docs · Integrations · Connect · Cloud · Discussions · Contributing
Every agent team eventually asks: Why did it say that? Why did it call that tool? ZizkaDB links every agent step to the step that caused it, so you get the answer in one call instead of scrolling through traces. That causal record is also the agent's auditable memory for its next run, and a tamper-evident audit log you can prove was never changed: causal observability for AI agents, from debugging to compliance.
parent_id. db.why(event_id) walks back to the user message, wrong tool, or bad context that started it.db.at(agent, timestamp) rebuilds exactly what the agent knew at any past moment.db.verify_chain(agent) proves nothing was edited, removed or reordered. GDPR deletions leave a content-free tombstone. A verifiable record for EU AI Act Article 12.db.context_for(agent, task) returns the relevant past as a prompt block, ranked by relevance, importance and recency; a new fact can replace an old one (supersedes). Keyword search works with no OpenAI key, hybrid with embeddings, or embed locally.In plain words: ZizkaDB is a flight recorder for AI agents. It records every step an agent takes and which step led to it, so when an agent does something unexpected, you can see exactly why.
| You are… | Go to |
|---|---|
| New to ZizkaDB, or not technical | ZizkaDB Cloud: nothing to install |
| A developer trying it on your laptop | Quickstart: one command, about a minute |
| Adding it to an agent you already have | Connect your agent |
| Running it for your team on a server | Self-host on a server or Deploy on Redu Cloud |
One command, one container. No repo clone, no Python, no config files.
1. Run it. With Docker running:
curl -fsSL https://raw.githubusercontent.com/ZIZKA-AI-SL/ZizkaDB/main/scripts/quickstart-remote.sh | bash
This pulls a single image (Postgres, the API and the dashboard together), starts it, and logs a demo agent run. After the download, startup takes a few seconds.
2. See why. It prints the causal chain behind the demo agent's tool call:
tool_call · lookup_order · ORD-8842
└── llm_response · gpt-4o
└── user_message · Why was my order delayed?
3. Explore. The dashboard opens on that agent, already signed in: localhost:3001/dashboard/activity?agent=support-bot. Click any event → Why? (causal) tab.
Now log your own agent: pip install zizkadb-sdk, then see CONNECT.md. The local API is http://localhost:8000 with key zizkadb_dev_local.
The script is a wrapper around this:
docker run -d --name zizkadb -e ENV=development \
-p 127.0.0.1:8000:8000 -p 127.0.0.1:3001:3001 \
-v zizkadb_data:/data ghcr.io/zizka-ai-sl/zizkadb
| Do this | Command |
|---|---|
| Stop / start | docker stop zizkadb / docker start zizkadb |
| Logs | docker logs -f zizkadb |
| Upgrade (keeps data) | re-run the quickstart command |
| Erase everything | docker rm -f zizkadb && docker volume rm zizkadb_data |
| Dashboard port busy | ZIZKADB_DASHBOARD_PORT=3005 before the quickstart command |
The single container has two modes:
On your own machine (-e ENV=development, what the quickstart uses): one-click sign-in and a well-known API key, with the ports bound to 127.0.0.1 only.
On a server (the default, production mode): the container generates its own secrets on first start, and the dashboard and API share port 3001. Sign in with the admin token:
docker run -d --name zizkadb -p 3001:3001 -v zizkadb_data:/data ghcr.io/zizka-ai-sl/zizkadb
docker exec zizkadb sed -n 's/^GEN_SELFHOST_ADMIN_TOKEN=//p' /data/secrets.env # your admin token
Put it behind HTTPS, and set ZIZKADB_PUBLIC_URL=https://your-domain so the links it generates are correct. If a reverse proxy on the same host forwards to it, add -e TRUSTED_PROXIES=127.0.0.1,::1,172.16.0.0/12 so sign-in rate limits see each visitor.
The single container runs without Qdrant: search and context_for() use keyword search there (no setup, no OpenAI key). For vector search, use the full stack below with embeddings on.
The self-hosted dashboard is just your dashboard: no signup, no email, no account. Accounts and plans exist only on ZizkaDB Cloud.
Self-hosted is single-agent: the first agent name you log with becomes your agent, and a second name is rejected with a message naming it. The support-bot demo agent does not count. For several agents, use ZizkaDB Cloud.
The full stack (Postgres, Qdrant, Redis, API, dashboard as separate containers) — use this for development, vector search, or production. It generates random database, Redis and Qdrant passwords on first setup:
git clone https://github.com/ZIZKA-AI-SL/ZizkaDB.git && cd ZizkaDB
bash scripts/setup-local.sh
| Service | URL |
|---|---|
| API | http://localhost:8000 |
| Dashboard | http://localhost:3001 |
| Swagger | http://localhost:8000/swagger |
On a machine other people can reach:
cp .env.example infra/.env
bash scripts/init-secrets.sh # random Postgres, Redis, Qdrant and JWT secrets
Then set these in infra/.env before starting the stack:
ENV=production # turns off the one-click button and dev API keys
DEV_API_KEY=<random> # must not be the default, or the API refuses to start
DEPLOYMENT_MODE=self_hosted
SELFHOST_ADMIN_TOKEN=<long-random> # python -c "import secrets; print(secrets.token_urlsafe(32))"
Optional: EVENT_RETENTION_DAYS (delete old events), METRICS_TOKEN (Prometheus /metrics), REDACT_PATTERNS (redact emails, phones, cards before storage). Data ports stay on 127.0.0.1.
The dashboard then asks for the admin token instead of showing the one-click button. Without SELFHOST_ADMIN_TOKEN, dashboard login stays disabled. Everyone who has the token signs in to the same single owner workspace. Check your config with bash scripts/validate-selfhost-config.sh --production. Full steps: wiki/Self-Hosting.
Redu Cloud is ZizkaDB's recommended cloud for the open-source edition. With the redu MCP added to your coding agent, ask it to "Deploy https://github.com/ZIZKA-AI-SL/ZizkaDB to redu". The agent follows redu.md: the single container on one VM, the dashboard and API on one HTTPS URL, and your data kept in a volume. Then sign in with the admin token, create your API key in Settings, and set ZIZKADB_HOST and ZIZKADB_API_KEY in your agent.
Full guide: DEVELOPMENT.md · Troubleshooting: wiki/Troubleshooting.md · What ZizkaDB sends: docs/telemetry.md
Works with the agent framework you already use — add one package and every step is logged with its cause.
Click a name for its setup guide. New project? Scaffold one with zizkadb init my-agent --template basic.
import asyncio
from zizkadb import ZizkaDB
async def main():
async with ZizkaDB(host="http://localhost:8000") as db:
user = await db.log(agent="my-bot", event="user_message", data={"text": "Why is my order late?"})
tool = await db.log(agent="my-bot", event="tool_call", data={"tool": "lookup_order"}, parent_id=user.event_id)
(await db.why(tool.event_id)).print()
asyncio.run(main())
import { ZizkaDB } from 'zizkadb-sdk'
const db = new ZizkaDB({ host: 'http://localhost:8000' })
const user = await db.log({ agent: 'my-bot', event: 'user_message', data: { text: 'Why is my order late?' } })
const tool = await db.log({ agent: 'my-bot', event: 'tool_call', data: { tool: 'lookup_order' }, parentId: user.eventId })
;(await db.why(tool.eventId)).print()
From the terminal: zizkadb why <event_id>. Full guide: CONNECT.md
| Function | What you get | |
|---|---|---|
| Debug | db.why(event_id) | The causal chain behind any event |
db.at(agent, timestamp) | What the agent knew at a past moment | |
db.baseline(agent) | Drift detection: alerts when behavior shifts from past sessions | |
| Causal agent memory | db.context_for(agent, task) | Relevant past events as a prompt block (relevance × importance × recency) |
db.search(query, mode=) | Keyword search out of the box; hybrid keyword + vector with embeddings | |
db.log(..., supersedes=, importance=) | Replace an outdated fact; weight what matters | |
| Audit | db.verify_chain(agent) | Proof that no event was edited, removed or reordered |
db.forget(key, value) | GDPR erasure, including the search index, leaving a tombstone (no content; its chain link and checksum let someone with database access confirm an exact guessed event) | |
db.export_events(agent) / db.import_events(...) | Portable NDJSON copy; move between self-host and Cloud | |
| Operate | db.log(..., idempotency_key=) / db.log_batch(events) | Safe retries; up to 500 events per request |
db.iter_events(agent) | Every event, cursor-paged | |
| Server settings | Retention, redaction, read-only and expiring keys, /metrics, backup and restore |
Article 12 of the EU AI Act requires high-risk AI systems to automatically keep logs of what they did. ZizkaDB gives you that record:
GET /v1/events/verify reports any row whose fields no longer match. Events are also hash-chained per agent, so GET /v1/events/chain proves no event was removed, inserted or reordered (GDPR deletions leave a content-free tombstone).db.at().db.baseline() flags when an agent starts behaving differently from its history.ZizkaDB supports your record-keeping obligations; it doesn't make a system compliant on its own.
flowchart LR
A[Your agent<br/>SDK · LangChain · CrewAI · LiveKit] -->|events + parent_id| B[ZizkaDB API]
D[Dashboard] --> B
M[MCP server<br/>Cursor · Claude] --> B
B --> P[(PostgreSQL<br/>events · hash chain · keyword search)]
B -.->|embeddings on| Q[(Qdrant<br/>vector search)]
B --> R[(Redis<br/>cache · rate limits)]
why() is one recursive query), its checksum and its link in the agent's hash chain. Keyword search is Postgres full-text search, so search works with nothing else installed.Ask Cursor or Claude "why did support-bot call lookup_order?" and get the chain back. Add this to your MCP config:
{
"mcpServers": {
"zizkadb": {
"command": "uvx",
"args": ["zizkadb-mcp"],
"env": { "ZIZKADB_HOST": "http://localhost:8000" }
}
}
}
For ZizkaDB Cloud, use ZIZKADB_API_KEY instead. Setup for each client: mcp/README.md. The MCP server is MIT-licensed; everything else is AGPL-3.0 (NOTICE).
Tracing tools such as Langfuse and LangSmith observe span trees. Memory layers such as Mem0 recall facts. ZizkaDB records why each decision happened, keeps it as auditable memory, and lets you prove the record is intact. Use it alongside a tracer if you already have one.
| ZizkaDB | LLM tracing tools | Agent memory layers | |
|---|---|---|---|
| Explicit cause → effect links | ✅ | Span nesting | — |
One-call root cause (db.why()) | ✅ | Manual trace reading | — |
| Time-travel to past agent state | ✅ | — | — |
Memory for future runs (db.context_for()) | ✅ | — | ✅ |
| Tamper-evident hash chain, verifiable in one call | ✅ | — | — |
| GDPR erasure that leaves proof (tombstones) | ✅ | — | — |
| Self-hosted search with no LLM key | ✅ | — | — |
— means not a core feature of that category; check each tool for specifics.
The same features, hosted at db.zizka.ai. No Docker to maintain.
| Pro | Team | |
|---|---|---|
| Price | €29 / mo | €69 / mo |
| Events / mo† | 50k | 100k |
| API keys | 2 | 5 |
† Plan targets on managed cloud; not enforced in API yet. See docs/README.md.
What is ZizkaDB?
An open-source database built for AI agents. It records every agent action as an event linked to the event that caused it, so you can see why a decision was made (why()), what the agent knew at any past moment (at()), and prove the history wasn't changed (verify_chain()). It's the record of what the agent actually did, independent of the LLM.
Is ZizkaDB free?
Self-hosting is free and open source (AGPL-3.0; the MCP server is MIT): one agent with one API key, data on your own servers. ZizkaDB Cloud is the paid managed service, with multiple agents, agent fleets and agent-to-agent message recording.
Does ZizkaDB need an OpenAI key?
No. Keyword search works with no embedding provider. Semantic and hybrid search can embed locally, use OpenAI, or use your own key.
Do I need to clone this repo?
No. The curl quickstart downloads config and Docker images only.
Do I need an API key locally?
No. http://localhost:8000 uses a built-in dev key.
Do I need an OpenAI key?
No. Logging, why(), time travel, keyword search and context_for() work without one. Add an OpenAI key, or run a local embedding model (EMBEDDINGS_PROVIDER=local with Ollama, LM Studio or vLLM), for hybrid vector search.
How is ZizkaDB different from an agent memory layer like Mem0?
A memory layer stores facts to recall. ZizkaDB stores what the agent did and why, linked step by step, and serves the relevant part back as memory (context_for()). The same record is a tamper-evident audit log, so memory, debugging and compliance come from one source.
Is ZizkaDB an observability tool?
It's causal observability for AI agents: instead of a span tree to read through, every event points to the event that caused it, and db.why() returns the chain. It works next to tracing tools such as Langfuse or LangSmith.
Can I use ZizkaDB as an audit log for the EU AI Act (Article 12)?
Yes, as the record-keeping part: every event is checksummed and hash-chained per agent, verify_chain() proves nothing was edited, removed or reordered, and GDPR erasure leaves a tombstone. It supports your obligations; it doesn't make a system compliant on its own.
How do I prove the logs weren't changed?
db.verify_chain(agent) (or GET /v1/events/chain) rechecks every checksum and link and returns the chain head. Store the head somewhere else; checking again later from that head proves nothing before it was rewritten.
My server's login page asks for an admin token. Where is it?
A server install generates one on first start. Single container: docker exec zizkadb sed -n 's/^GEN_SELFHOST_ADMIN_TOKEN=//p' /data/secrets.env. Full stack: the SELFHOST_ADMIN_TOKEN you set in infra/.env. After signing in, create your API key in Settings.
Where does my data go?
When you self-host, everything stays on your machine. The server and dashboard make no outside requests; the SDKs send one anonymous install ping, which ZIZKADB_TELEMETRY=false turns off. Details: docs/telemetry.md.
zizkadb demo says connection refused?
The stack isn't running. Start it with the curl command above or bash scripts/setup-local.sh.
| Worked example | worked/01-support-order-delay |
| Examples | examples/ |
| Self-hosting | DEVELOPMENT.md · wiki/Self-Hosting |
| Integrate any agent | docs/integrate/ |
| Issues · Discussions | Issues · Discussions |
| Security | SECURITY.md |
| AI-assisted development | AGENTS.md |
Thanks to everyone who has helped build ZizkaDB. Want to join? Read CONTRIBUTING.md or pick up an open issue.