---
title: Architecture
summary: "The path a request takes through the stack, and where the open-core line falls."
canonical: https://docs.caveman.so/docs/architecture
updated: 2026-08-26T03:57:26+02:00
basis: inferred
---

# Architecture

> The path a request takes through the stack, and where the open-core line falls.
<DocSchema slug="architecture" />

Caveman is not one program. It is four pieces that compose, and most people only ever install one of
them. This page shows how a single request moves through them and why the pieces are separable.

## One request

[Diagram: one request, from your agent through the skill and the engine to the provider, with a recovery path back.]

The agent decides what to say. The skill has already shaped how it says it. The engine reduces whatever
payload is about to leave. The provider bills for what arrives.

The dashed line is the part that makes the rest defensible. Compression here is not a one-way door. Before
the engine emits a smaller payload it writes the original bytes to a local store keyed by a hash of those
bytes, and the compressed output carries that handle. An agent that needs the part that was removed asks
for the handle and gets the original back, byte for byte, in the same turn.

<Note title="No store, no compression">
The rule the engine follows has three possible outcomes and no fourth: the payload is compressed and
recoverable, or it passes through untouched, or it is recovered. If the recovery store is unavailable, the
engine does not compress. It passes the original through.
</Note>

## Why the pieces are separable

Each layer answers a different question, and they fail independently.

- Skill: Changes what the agent writes. No process, no config, no network.
- Engine: Changes what a payload weighs. A binary you run, or a library you link.
- Memory: Changes what you have to say twice. A local SQLite store.
- Cloud: Changes what you can prove to someone else. An account, across a network.

Nothing above a layer is required by the layer below it. The skill does not know the engine exists. The
engine does not need an account. This is why the licence split follows the same lines rather than
cutting across them.

## Where the open-core line falls

[Diagram: the licence split across MIT, BSL 1.1 and Commercial surfaces.]

The rule that governs new code is one sentence: a module that imports, links, embeds or ships as part of
the engine-linked runtime is BSL 1.1 unless a decision record explicitly classifies it as an adoption
surface.

The practical effect for you is in the additional use grant. BSL 1.1 here permits internal evaluation,
local development, CI, integration, and self-hosted use for your own first-party traffic, production
included. What it does not permit is offering Caveman's functionality to third parties as a hosted or
embedded service. That boundary is the commercial line, and it is the only one.

Each BSL release converts to Apache 2.0 on the earlier of 21 June 2030 or four years after that version
was first distributed.

## Content detection

The engine does not ask you what a payload is. It reads the bytes and decides, then routes to a
compressor built for that shape. The types it recognises:

`json` · `log` · `code` · `diff` · `search-result` · `text` · `toon` · `html` · `a11y` · `terminal` ·
`tabular` · `config`

Two compressors are never chosen automatically and have to be asked for by name: the tool-schema
compressor and the TOON encoder. Automatic selection of either would surprise a caller who did not opt
in.

When detection is not confident, it answers `text`, which is the compressor that removes the least. Every
unknown case in this system resolves toward doing less, not more.

## Failure behaviour

This is worth stating on its own, because it is the part that decides whether you can leave the thing
switched on.

```text
unknown mode          -> record, which never transforms
transform error       -> forward the original bytes
result not smaller    -> keep the original
low-confidence type   -> text
unknown grader        -> passed: false
unknown model price   -> zero, tagged unpriced
```

Every one of those resolves to the conservative answer. A compression system that is willing to guess is
a compression system you have to babysit.
