somm explained · Page 1 of 6

Overview

somm is a zero-config Python library that routes LLM calls across providers, records every call in a local SQLite database, and turns the accumulated telemetry into evidence-backed model recommendations — with no hosted control plane and no commercial dependency on the hot path.

What somm is: telemetry, routing, and an intelligence loop

An application creates a client with somm.llm(project=...) and submits named workloads through generate(). Each call is routed through eligible providers and recorded in a project-local .somm/calls.sqlite database with provider, model, token, cost, latency, and outcome data (README.md:67). That is the whole required footprint: a library call in, a routed response and a telemetry row out.

Everything else is layered on that substrate. Calls, workloads, optional samples, evaluations, model intelligence, provider health, and recommendations all share one SQLite data model (docs/BLUEPRINT.md:118). When the optional somm serve service is running, scheduled workers grade sampled calls, refresh model metadata, and produce recommendations; the MCP server and web dashboard read the same local state (notes/PLAN.md:69). Services consume calls to produce evaluations and recommendations without ever rewriting the original telemetry (docs/BLUEPRINT.md:171).

flowchart LR
  A["somm.llm(project=...)"] --> C["SommLLM client"]
  C --> R["Router"]
  R --> P["Provider adapters"]
  C --> DB[("project-local SQLite\n.somm/calls.sqlite")]
  subgraph serve ["Optional: somm serve"]
    W["Background workers\n(model intel, shadow eval, agent)"]
    UI["Web dashboard"]
  end
  W --> DB
  UI --> DB
  W --> REC["Recommendations"]
  MCP["somm-mcp\n(coding-agent tools)"] --> DB

The core bet: local-first, privacy-first, zero-config

Zero-config means configuration resolves in layers — built-in defaults, the project's pyproject.toml, environment variables, then explicit arguments — before selecting a project-local or registered database (packages/somm-core/src/somm_core/config.py:84). In the default observe mode, unknown workloads auto-register so adoption needs no ceremony; strict mode turns a missing registration into an error when governance matters (packages/somm/src/somm/client.py:658).

Local-first means the database is user-owned. Constructing a repository creates a permission-restricted SQLite file, applies migrations automatically, and configures WAL for continuous local writes with concurrent readers (packages/somm-core/src/somm_core/repository.py:177). Cost tracking works offline from a bundled pricing snapshot shipped inside the wheel (packages/somm-core/src/somm_core/pricing.py:108), and paid intelligence sources stay off the default path (ROADMAP.md:237). CI enforces the speed of this bet mechanically: a performance gate measures clean import latency and a 500-call warmed hot path against a fake provider, failing when medians exceed budget (scripts/check_perf_budget.py:96).

Privacy-first is structural, not aspirational. Prompt and response bodies are stored only through opt-in sampling; databases use owner-only permissions (packages/somm-core/src/somm_core/repository.py:185). Privacy is enforced independently in routing, workers, SQL views, file permissions, and localhost service defaults (docs/threat-model.md:44). A workload registered as private is restricted to local providers — and if none are available, the call fails rather than sending data upstream (examples/private_workload.py:27).

Fail open vs. fail closed — a deliberate split Advisory intelligence fails open so it can never break live inference: missing pricing becomes zero cost, unreadable fleet databases contribute zero (packages/somm-core/src/somm_core/pricing.py:240), and hook failures cannot break the call path (docs/plugins.md:79). Hard budgets fail closed: refusal is fatal and happens before dispatch, so provider fallback can't route around a spending cap (docs/errors/SOMM_BUDGET_EXCEEDED.md:23).
Telemetry is append-only. Intelligence is advisory. Budgets are law. — the design stance, per docs/BLUEPRINT.md:56, packages/somm-core/src/somm_core/pricing.py:240, and docs/errors/SOMM_BUDGET_EXCEEDED.md:23

Workloads, not providers, as the stable identity

The unit of identity in somm is not a provider or a model — it's the workload. Workload names unify policies, budgets, evaluation, and recommendations (README.md:92), and each workload carries privacy classification, budget ceilings, and capability requirements (docs/BLUEPRINT.md:118). Because the workload names the task rather than the vendor, telemetry stays comparable when routing changes underneath it (packages/somm-skill/src/somm_skill/SKILL.md:44).

This is what makes the intelligence loop possible. The router filters explicitly incapable provider/model pairs before any network access, applies quota pacing, skips cooled-down providers, and falls through transient failures (packages/somm/src/somm/routing.py:158) — but because every one of those decisions is recorded against a workload, the system can later answer "which model actually serves this task best?" with evidence instead of vibes. Recommendations expose their supporting evidence and require the user to apply them; nothing rolls out automatically (docs/BLUEPRINT.md:255).

The six packages at a glance

A uv workspace separates the system into six independently published packages (README.md:528, pyproject.toml:7), each with its own PyPI trusted-publishing environment (.github/workflows/publish.yml:28):

PackageRoleAnchor
somm The main library and CLI: provider routing, telemetry, cost and budget controls, prompt management, evaluation, diagnostics. packages/somm/src/somm/client.py:910
somm-core Dependency-free foundation: typed records, SQLite persistence and migrations, config, pricing, quota accounting, graders. packages/somm-core/src/somm_core/repository.py:177
somm-service The localhost control plane: dashboard, telemetry APIs, an Anthropic-compatible proxy, and background intelligence workers. packages/somm-service/src/somm_service/app.py:1285
somm-mcp A stdio MCP server exposing telemetry, recommendations, comparisons, replay, and decision memory to coding agents. packages/somm-mcp/src/somm_mcp/server.py:59
somm-langchain A thin adapter making somm's routed runtime look like a standard LangChain chat model. packages/somm-langchain/src/somm_langchain/chat_model.py:32
somm-skill A dependency-free agent playbook: Markdown guidance teaching coding agents the telemetry and model-selection loop. packages/somm-skill/src/somm_skill/SKILL.md:6

The dependency shape is deliberate: somm-core has no dependencies at all (packages/somm-core/README.md:3), the client keeps the hot path self-hosted, and everything above — service, MCP, LangChain, skill — is optional. Provider dispatch never leaks into the foundation.

By the numbers

42klines of Python
6publishable packages
v20one shared SQLite schema
14MCP tools for agents

The single schema is the load-bearing number. Schema v20 evolves the original workload/prompt/call ledger into decisions, workload revisions, datasets, evaluation receipts, campaigns, canonical model aliases, and serving SLOs (packages/somm-core/src/somm_core/version.py:7) — and every layer of the system, from the router to the dashboard to the MCP tools, reads and writes that one model. Migrations commit DDL and version stamps together, so a database is never left partially upgraded (packages/somm-core/src/somm_core/schema.py:91). A release gate requires every workspace package to share a single version with exact internal pins (scripts/check_release_gate.py:54), and CI runs the whole matrix on Python 3.12 and 3.13 (.github/workflows/ci.yml:9).

How to read this site

The pages follow the data. Start with a single call and follow it outward — through the substrate it lands in, the loop that learns from it, the agents that consume it, and the engineering that keeps it honest.

The Life of a Call

From generate() through workload resolution, hooks, budget checks, routing, fallback, and the telemetry row it leaves behind.

The Data Substrate

The SQLite schema, append-only call records, opt-in sampling, owner-only permissions, and privacy enforced at every layer.

The Intelligence Loop

Model-intel refresh, shadow evaluation against gold models, and how graded evidence becomes recommendations you apply — never auto-rollout.

Agents and Integrations

The 14 MCP tools, the LangChain adapter, drop-in compatibility shims, and the skill files that teach coding agents the loop.

Engineering Reference

CI gates, performance budgets, the release process, security posture, and the scripts that turn project invariants into executable checks.