Copied to clipboard

Reference

Technical reference for tapes providers, storage backends, and data model.

Config File

Configuration is stored in .tapes/config.toml. tapes looks for config in this order:

  1. ./.tapes/config.toml — local project directory
  2. ~/.tapes/config.toml — user home directory
# .tapes/config.toml
version = 0

[storage]
postgres_dsn = "postgres://tapes:tapes@localhost:5432/tapes?sslmode=disable"

[publisher.kafka]
# brokers = "localhost:9092"
# topic = "tapes.nodes.v1"
# client_id = "my-app"

[proxy]
provider = "anthropic"
upstream = "https://api.anthropic.com"
listen = ":8080"
project = "my-app"

[api]
listen = ":8081"
# web_ui = true

[ingest]
listen = ":8082"

[client]
proxy_target = "http://localhost:8080"
api_target = "http://localhost:8081"

[vector_store]
# target defaults to storage.postgres_dsn
target = ""

[embedding]
provider = "ollama"
target = "http://localhost:11434"
model = "embeddinggemma"
dimensions = 768

[opencode]
provider = "anthropic"
model = "claude-sonnet-4-5"

[telemetry]
disabled = false

[update]
# disabled = true

Precedence

Configuration values are resolved in this order (highest to lowest priority):

  1. CLI flags — Always override everything
  2. Environment variablesTAPES_* prefixed variables (see env var reference)
  3. Config file — Values set in config.toml
  4. Defaults — Built-in default values

Use tapes config list to see all current values. See CLI config for management commands.

Providers

tapes works with any LLM provider. Configure using --provider and --upstream flags.

Provider Upstream URL
Ollama (default) http://localhost:11434
Anthropic https://api.anthropic.com
OpenAI https://api.openai.com

The --provider flag tells tapes how to parse the API format. The -u flag specifies where to forward requests.

Storage

tapes uses PostgreSQL for all storage. The same database holds the Merkle DAG, session aggregates, and vector embeddings.

PostgreSQL (required) Pass --postgres "postgres://user:pass@host:5432/tapes" to enable. The database must have the pg_duckdb and pgvector extensions installed. Schema migrations run automatically on startup. See the PostgreSQL Storage guide.
Local bootstrap Run tapes local up to start a Postgres container with pg_duckdb + pgvector preinstalled and an Ollama container alongside it.

Streaming

tapes can publish DAG node events to an external stream alongside storage. Publishing is best-effort — storage remains authoritative.

Kafka Publish conversation events to Kafka topics, partitioned by conversation root hash. Use --kafka-brokers and --kafka-topic to enable. See the Kafka Streaming guide.

Vector Storage

Semantic search for stored conversations. When an embedding provider is configured, tapes generates embeddings on each turn and stores them in the same Postgres database via pgvector.

pgvector (built-in) Embeddings live in the same Postgres database as the Merkle DAG. No separate vector service to run. Defaults to the --postgres DSN; override with --vector-store-target if you keep embeddings in a different database.
Ollama Embeddings Default embedding model is embeddinggemma. tapes local up pulls it automatically; otherwise install with ollama pull embeddinggemma.
OpenAI Embeddings Run tapes auth openai (or set OPENAI_API_KEY) and tapes config set embedding.provider openai.
tapes serve \
  --postgres "postgres://tapes:tapes@localhost:5432/tapes?sslmode=disable" \
  --embedding-provider ollama \
  --embedding-target http://localhost:11434 \
  --embedding-model embeddinggemma

/v1/stats response

The GET /v1/stats endpoint returns aggregate counts and rollups across the matching node set. All numbers come from a single storage-driver aggregate — there is no per-session chain walk.

{
  "session_count": 142,
  "turn_count": 3870,
  "root_count": 142,
  "completed_count": 119,
  "total_cost": 12.4538,
  "input_tokens": 1842301,
  "output_tokens": 412057,
  "total_duration_ns": 9381240000000,
  "tool_calls": 2841
}
Field Description
session_count Distinct session heads in the matched window.
turn_count Total nodes matching the filter (each turn = one node).
root_count Distinct DAG roots in the matched window.
completed_count Sessions whose head is an assistant leaf with a terminal stop_reason (stop, end_turn, end-turn, eos).
total_cost USD cost folded from per-model token rollups using the configured pricing table.
input_tokens / output_tokens SUM over every matching node — each token billed counted exactly once.
total_duration_ns Wall-clock span MAX(created_at) − MIN(created_at) across matching nodes, in nanoseconds.
tool_calls SUM of tool invocations across matching nodes.

Filter with the same query parameters as /v1/stems: project, agent_name, model, provider, since, until. (The product session list at /v1/sessions takes only limit and cursor.)

Bucket Data Model

Each conversation turn is stored as a Bucket containing:

type Content kind (e.g. message)
role Message role (system, user, assistant, tool)
content Message content blocks
model Model identifier
provider Provider that handled the request
agent_name Agent harness that produced the turn (e.g. claude, opencode, codex)

Buckets are hashed and stored in a Merkle DAG structure for cryptographic verification.

Last updated: