Memory library for building stateful agents
Go to file
Vineeth Voruganti b65d03d297
Refactor clients.py to add modern features and more flexible configuration (#459)
* fix: Add JSON repair for truncated LLM responses across all providers and Gemini thinking budget support

LengthFinishReasonError from OpenAI-compatible providers (custom, openai, groq) was crashing the deriver
with 14k+ occurrences in production. The vLLM path already had repair logic but it was gated on
provider=="vllm", unreachable when routing through litellm as a custom provider.

- Extract shared _repair_response_model_json() helper for all providers
- Catch LengthFinishReasonError in OpenAI/custom parse() path and repair truncated JSON
- Add repair fallback to Anthropic and Gemini response_model paths
- Add repair fallback to Groq response_model path
- Pass thinking_budget_tokens to Gemini 2.5 models via thinking_config
- Add 14 tests covering repair paths for all providers and Gemini thinking budget

Fixes HONCHO-YC

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: live llm integration tests

* feat: Consistent Model Config Protocol

* fix: migrate the remaining app callers off the legacy llm_settings path

* fix: Docs and regression tests

* fix: refactor llm runtime path to model-config-only API

* fix: refactor config to nested model-config source of truth

* fix: refactor llm streaming and tool dispatch through backends

* fix: cut over llm config to nested model_config only

* fix: collapse vllm and custom into openai_compatible transport

* feat: refactor llm config to explicit transports and bare model ids

* feat: (embed) Add configurability for embedding model

* fix: tests for embedding provider

* fix: Address Review Comments

* fix: (llm) remove Groq backend and per-vendor base URLs

* chore: move llm tests

* fix: (llm) address review findings — config regressions, backend bugs, dead code

* fix: address backend end silly errors

* chore: (docs) update configuration and self-hosting guides

* chore: fix tests

* fix: address code rabbit comments

* fix: add validation to the dream settings

* fix: further address code rabbit comments

* fix: Address Code Rabbit Comments

* fix: Another round of code rabbit

* fix: Address Code Rabbit Nits

* fix: tests

* refactor: rename thinking validator to reflect transport scope

_validate_anthropic_thinking_minimum only enforces the >=1024 rule for
Anthropic and no-ops for other transports, so the name was misleading
now that it's shared across ConfiguredModelSettings, FallbackModelSettings,
and ModelConfig. Renamed to _validate_thinking_constraints with a docstring
clarifying per-transport behavior. No logic change.

* fix(config): drop transport-specific thinking params when env override changes transport

_fill_defaults_for_nested_field previously preserved the default MODEL_CONFIG's
thinking_budget_tokens/thinking_effort across a transport override. This leaked
Gemini-family defaults (e.g. thinking_budget_tokens=1024) into OpenAI-transport
overrides, and the OpenAI backend then correctly rejected the unsupported param
at call time (OpenAI uses reasoning.effort, not a token budget).

The helper now strips thinking_budget_tokens and thinking_effort from the
default dict when the env override supplies a transport different from the
default's. Explicit thinking params in the override are preserved.

* fix(config): apply thinking-param strip to dialectic level merge too

DialecticSettings._merge_level_defaults does its own inline MODEL_CONFIG
merge (parallel to _fill_defaults_for_nested_field), so the previous fix
missed dialectic-level overrides. E.g. flipping
DIALECTIC_LEVELS__minimal__MODEL_CONFIG__TRANSPORT from gemini (default)
to openai still leaked the default thinking_budget_tokens=0 into the
openai config, which the OpenAI backend then rejected at call time.

The level-merge path now applies the same 'strip transport-specific
thinking params when transport changes' rule as the generic helper.
Added a regression test exercising the merge validator directly.

* refactor(llm): wire ModelConfig knobs through, prune clients.py migration leftovers

Three connected fixes to finish carving the LLM stack out of src/utils/clients.py
and into src/llm/:

1. Propagate ModelConfig tuning knobs into backend calls.
   honcho_llm_call_inner built extra_params from only {json_mode, verbosity},
   silently dropping top_p, top_k, frequency_penalty, presence_penalty, seed,
   and operator-supplied provider_params from any ModelConfig. Thread the
   selected config through ProviderSelection and merge
   build_config_extra_params(selected_config) into extra_params; per-call
   kwargs still win over provider_params defaults. Makes
   _build_config_extra_params public as build_config_extra_params so
   clients.py and request_builder.py share one translation. Adds
   TestModelConfigExtraParamsPropagation covering OpenAI/Anthropic knob
   propagation, provider_params passthrough, and per-call override
   precedence.

2. Drop dead extract_openai_* duplicates in clients.py.
   extract_openai_reasoning_content, extract_openai_reasoning_details, and
   extract_openai_cache_tokens had no callers outside their own definitions
   — the live implementations live in src/llm/backends/openai.py. -103
   lines from clients.py.

3. Unify on ModelTransport, delete SupportedProviders.
   The "google" vs "gemini" split forced a _provider_for_model_config
   translation shim in two places. Replace all SupportedProviders usages
   with ModelTransport, rename CLIENTS["google"] → CLIENTS["gemini"],
   update provider branches + LLMError labels + reasoning-trace entries
   accordingly. Trace JSONL now writes "provider": "gemini" instead of
   "google" — consistent with the broader env-var rename cutover.

Also tidies up pre-existing basedpyright findings in tests/llm/test_model_config.py
(pydantic before-validator dict inputs + descriptor-proxy call).

ruff: clean. basedpyright: 0 errors, 0 warnings. Tests: 153/153 pass across
tests/utils/test_clients.py, tests/utils/test_length_finish_reason.py,
tests/llm/, tests/dialectic/, tests/deriver/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(llm): finish the src/utils/clients.py → src/llm/ migration

honcho_llm_call_inner now delegates to request_builder.execute_completion
and execute_stream instead of re-implementing backend call scaffolding
inline. The new _effective_config_for_call helper carries per-call kwargs
(temperature, stop_seqs, thinking_budget_tokens, reasoning_effort) onto
the selected ModelConfig — or synthesizes a minimal config for the
test-only callers that pass provider+model directly. max_output_tokens
is zeroed on the effective config to preserve the current
"per-call max_tokens wins" semantic; honoring ModelConfig.max_output_tokens
is a separable correctness concern.

Side effect of routing through the new path: ConfiguredModelSettings'
thinking_budget_tokens validator now fires on synthesized configs.
test_anthropic_thinking_budget was asserting that a sub-1024 budget
propagated to Anthropic — bumped to 1024 to match what Anthropic actually
accepts.

Unified client construction. Promoted the cached client factories in
src/llm/__init__.py (get_anthropic_client, get_openai_client,
get_gemini_client, get_{anthropic,openai,gemini}_override_client) to
public API and added them to __all__. Promoted
credentials._default_transport_api_key → default_transport_api_key.
Deleted the duplicate _build_client and _default_credentials_for_provider
from clients.py; _client_for_model_config now falls through to the
public factories. CLIENTS dict and _get_backend_for_provider stay as the
mockable seam for the ~50 patch.dict(CLIENTS, {...}) test call sites.

Wired operator-configurable Gemini cached-content reuse end-to-end.
PromptCachePolicy moved from src/llm/caching.py into src/config.py so
ModelConfig can reference it as a field without a circular import;
caching.py re-exports the name for existing imports. Added
cache_policy: PromptCachePolicy | None on ConfiguredModelSettings,
FallbackModelSettings, ResolvedFallbackConfig, and ModelConfig.
resolve_model_config, _resolve_fallback_config, and
_select_model_config_for_attempt copy the field through.
honcho_llm_call_inner passes effective_config.cache_policy into
execute_completion / execute_stream, so operators opt in via
e.g. DERIVER_MODEL_CONFIG__CACHE_POLICY__MODE=gemini_cached_content
and the selection actually fires instead of sitting on a dead path.

New regression test test_cache_policy_reaches_gemini_backend asserts the
PromptCachePolicy object reaches the Gemini backend's extra_params.

ruff + basedpyright: clean. Tests: 154/154 pass across
tests/utils/test_clients.py, tests/utils/test_length_finish_reason.py,
tests/llm/, tests/dialectic/, tests/deriver/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(llm): move all LLM orchestration into src/llm/ and delete clients.py

The 1624-line src/utils/clients.py has been carved up into focused modules
under src/llm/ and deleted. There is now one golden path for LLM
orchestration and no dual entrypoint.

New module layout:

  src/llm/
    __init__.py       thin stable re-export surface
    api.py            public honcho_llm_call with retry + fallback + tool
                      loop delegation
    executor.py       honcho_llm_call_inner (single-call executor); bridges
                      to request_builder.execute_completion / execute_stream
    tool_loop.py      execute_tool_loop + stream_final_response, plus
                      assistant-tool-message and tool-result formatting
    runtime.py        AttemptPlan dataclass (replaces the loose
                      ProviderSelection NamedTuple), effective_config_for_call,
                      plan_attempt, per-retry temperature bump, attempt
                      ContextVar
    registry.py       single owner of CLIENTS dict + cached default and
                      override SDK-client factories + backend/history-adapter
                      selection + high-level get_backend(config)
    conversation.py   count_message_tokens, tool-aware message grouping,
                      truncate_messages_to_fit
    types.py          HonchoLLMCallResponse, HonchoLLMCallStreamChunk,
                      StreamingResponseWithMetadata, IterationData,
                      IterationCallback, ReasoningEffortType, VerbosityType,
                      ProviderClient
    request_builder.py low-level request assembly (ModelConfig → backend
                      complete/stream); no longer owns credential resolution
    credentials.py    default_transport_api_key, resolve_credentials
    caching.py        gemini_cache_store; re-exports PromptCachePolicy
                      from src.config
    backend.py        Protocol + normalized result types
    history_adapters.py provider-specific assistant/tool message shapes
    structured_output.py
    backends/         AnthropicBackend, OpenAIBackend, GeminiBackend

handle_streaming_response had no production callers; it is deleted. The
three tests that used it now drive honcho_llm_call_inner(stream=True,
client_override=...) directly, which exercises the same code path the
public API uses.

Dead credential passthrough removed. The ProviderBackend Protocol and
all three concrete backends no longer accept api_key / api_base — those
are baked into the underlying SDK client at registry construction time
and were being del'd everywhere they appeared. request_builder also
stops resolving and forwarding them.

Client construction is unified. The cached default-client factories
(get_anthropic_client, get_openai_client, get_gemini_client) and override
factories (get_*_override_client) are promoted to public API; the
module-level CLIENTS dict populates from them and remains the
patch.dict(CLIENTS, {...}) mocking seam tests rely on. Old duplicate
helpers (_build_client, _default_credentials_for_provider) are gone.
default_transport_api_key is promoted to public.

Application imports now come from src.llm (dreamer, dialectic, deriver,
summarizer, telemetry-adjacent tests). No code imports from
src.utils.clients anywhere in the repo.

ruff: clean. basedpyright: 0 errors, 0 warnings. Tests: 1013/1013 pass
across the entire non-infra test suite (excluding tests/unified,
tests/bench, tests/live_llm, tests/alembic).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(llm): sanitize tool schemas for Gemini's function_declarations validator

Gemini's native-transport function-declarations validator accepts a narrow
subset of JSON-Schema / OpenAPI: type, format, description, nullable, enum,
properties, required, items, minItems, maxItems, minimum, maximum, title.
Anything else — additionalProperties, allOf, if/then/else, $ref, anyOf,
oneOf, $defs, patternProperties — triggers an INVALID_ARGUMENT 400 at call
time.

Our agent tool schemas in src/utils/agent_tools.py use several of those
(additionalProperties: false, allOf + if/then conditionals) because they
were authored for OpenAI strict-mode + Anthropic, which need the richer
vocabulary. GeminiBackend._convert_tools was passing them straight through.

Add _sanitize_schema(): walks the parameters tree and drops unsupported
keywords while preserving semantics for the keywords that hold user data
(properties maps field-name → sub-schema; required / enum are lists of
literals; items is a single sub-schema). Other backends are untouched and
continue to receive the full strict schemas.

Regression tests:
- test_gemini_sanitize_schema_strips_unsupported_keywords: confirms
  additionalProperties, allOf + if/then, and $defs are stripped at nested
  levels while legitimate fields survive.
- test_gemini_convert_tools_sanitizes_parameters_schema: end-to-end
  _convert_tools output has no forbidden keys.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: fix tool calling syntax for gemini

* refactor(llm): normalize defaults, widen OpenAI reasoning-model routing

* chore: fix test

* fix(llm): address post-migration review feedback

* fix(llm): gemini robustness + dreamer specialist ergonomics

* chore: addres review comments

* chore: (docs) unrelease changelog addition

* chore: (docs) merge commit changes

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Erosika <eri@plasticlabs.ai>
2026-04-20 02:46:37 -04:00
.claude/skills feat: retry on more httpx exceptions (#467) 2026-04-03 12:20:53 -04:00
.github Fix typos (#440) 2026-03-22 15:52:55 -04:00
.vscode Typing (#137) 2025-06-24 18:29:13 -04:00
assets Docs Refresh (#200) 2025-08-29 16:27:07 -04:00
database Standardize DB Constraint Conventions (#272) 2025-11-20 11:50:54 -05:00
docker fix: add observability to docker compose + get docker compose into a usable state (#429) 2026-03-18 13:16:22 -04:00
docs Refactor clients.py to add modern features and more flexible configuration (#459) 2026-04-20 02:46:37 -04:00
examples feat(examples): add Honcho memory skill for Zo Computer (#495) 2026-04-06 17:06:08 -04:00
mcp refactor: MCP server improvements (#379) 2026-03-31 17:34:36 -04:00
migrations feat: make session_name nullable for documents and update related SDKs (#347) 2026-01-26 13:33:11 -05:00
scripts Oolong Benchmark (#323) 2026-02-23 16:55:59 -05:00
sdks feat: retry on more httpx exceptions (#467) 2026-04-03 12:20:53 -04:00
src Refactor clients.py to add modern features and more flexible configuration (#459) 2026-04-20 02:46:37 -04:00
tests Refactor clients.py to add modern features and more flexible configuration (#459) 2026-04-20 02:46:37 -04:00
.dockerignore Dialectic Endpoint Improvements (#67) 2024-09-14 17:06:11 -04:00
.env.template Refactor clients.py to add modern features and more flexible configuration (#459) 2026-04-20 02:46:37 -04:00
.gitignore feat(examples): add Honcho memory skill for Zo Computer (#495) 2026-04-06 17:06:08 -04:00
.markdownlint.json Add Pre-commit Hooks (#165) 2025-07-22 15:17:53 -04:00
.pre-commit-config.yaml sdks: add set peer card function (#371) 2026-02-09 15:35:57 -05:00
.python-version Switch from UUIDv4 to NanoID (#71) 2024-10-17 14:07:51 -04:00
CHANGELOG.md Refactor clients.py to add modern features and more flexible configuration (#459) 2026-04-20 02:46:37 -04:00
CLAUDE.md feat: consolidate db calls in session context (#380) 2026-02-13 11:54:41 -05:00
CONTRIBUTING.md Self-hosting docs overhaul: single-provider default, restructured config guide (#510) 2026-04-07 22:49:57 -04:00
Dockerfile fix(docker): remove api-specific healthcheck from shared image (#530) 2026-04-16 10:48:36 -04:00
LICENSE Initial commit 2023-09-10 17:29:55 -04:00
README.md Refactor clients.py to add modern features and more flexible configuration (#459) 2026-04-20 02:46:37 -04:00
alembic.ini Database Concurrency Optimizations (#80) 2024-12-13 11:56:39 -05:00
config.toml.example Refactor clients.py to add modern features and more flexible configuration (#459) 2026-04-20 02:46:37 -04:00
docker-compose.yml.example Self-hosting docs overhaul: single-provider default, restructured config guide (#510) 2026-04-07 22:49:57 -04:00
fly.toml switch OTEL metrics to prometheus (#344) 2026-01-25 17:26:42 -05:00
pyproject.toml Refactor clients.py to add modern features and more flexible configuration (#459) 2026-04-20 02:46:37 -04:00
uv.lock Refactor clients.py to add modern features and more flexible configuration (#459) 2026-04-20 02:46:37 -04:00

README.md


Static Badge PyPI version NPM version Discord

Honcho is an open source memory library with a managed service for building stateful agents. Use it with any model, framework, or architecture. It enables agents to build and maintain state about any entity--users, agents, groups, ideas, and more. And because it's a continual learning system, it understands entities that change over time. Using Honcho as your memory system will earn your agents higher retention, more trust, and help you build data moats to out-compete incumbents.

Honcho has defined the Pareto Frontier of Agent Memory. Watch the video, check out our evals page, and read the blog post for more detail.

TL;DR - Getting Started

With Honcho you can easily setup your application's workflow, save your interaction history, and leverage the reasoning it does to inform the behavior of your agents

Typescript examples are available in our docs.

  1. Install the SDK
# Python
pip install honcho-ai
uv add honcho-ai
poetry add honcho-ai
  1. Setup your Workspace, Peers, Session, and send Messages
from honcho import Honcho

# 1. Initialize your Honcho client
honcho = Honcho(workspace_id="my-app-testing")

# 2. Initialize peers
alice = honcho.peer("alice")
tutor = honcho.peer("tutor")

# 3. Create a session and add messages

session = honcho.session("session-1")
# Adding messages from a peer will automatically add them to the session
session.add_messages(
    [
        alice.message("Hey there — can you help me with my math homework?"),
        tutor.message("Absolutely. Send me your first problem!"),
    ]
)
  1. Leverage reasoning from Honcho to inform your agent's behavior

### 1. Use the chat endpoint to ask questions about your users in natural language
response = alice.chat("What learning styles does the user respond to best?")

### 2. Use session context to continue a conversation with an LLM
context = session.context(summary=True, tokens=10_000)

# Convert to a format to send to OpenAI and get the next message
openai_messages = context.to_openai(assistant=tutor)

from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
  model="gpt-4",
  messages=openai_messages
)

### 3. Search for similar messages
results = alice.search("Math Homework")

### 4. Get a session-scoped representation of a peer
alice_representation = session.representation(alice)

This is a simple example of how you can use Honcho to build a chatbot and leverage insights to personalize the agent's behavior.

Sign up at app.honcho.dev to get started with a managed version of Honcho.

Learn more ways to use Honcho on our developer docs.

Read about the design philosophy and history of the project on our blog.

Project Structure

The Honcho project is split between several repositories with this one hosting the core service logic. This is implemented as a FastAPI server/API to store data about an application's state.

There are also client SDKs implemented in the sdks/ directory with support for Python and TypeScript.

Examples on how to use the SDK are located within each SDK folder and in the SDK Reference

There are also documented examples of how to use the core SDKs in the API Reference section of the documentation.

Usage

Sign up for an account at https://app.honcho.dev and get started with $100 free credits. When you sign up you'll be prompted to join an organization which will have a dedicated instance of Honcho.

Provision API keys and change your base url to point to https://api.honcho.dev

Additionally, Honcho can be self-hosted for testing and evaluation purposes. See the Local Development section below for details on how to set up a local version of Honcho.

Local Development

Below is a guide on setting up a local environment for running the Honcho Server.

This guide was made using a M3 Macbook Pro. For any compatibility issues on different platforms, please raise an Issue.

Prerequisites and Dependencies

Honcho is developed using python and uv.

The minimum python version is 3.10 The minimum uv version is 0.5.0

Setup

Once the dependencies are installed on the system run the following steps to get the local project setup.

  1. Clone the repository
git clone https://github.com/plastic-labs/honcho.git
  1. Enter the repository and install the python dependencies

We recommend using a virtual environment to isolate the dependencies for Honcho from other projects on the same system. uv will create a virtual environment when you sync your dependencies in the project.

cd honcho
uv sync

This will create a virtual environment and install the dependencies for Honcho. The default virtual environment will be located at honcho/.venv. Activate the virtual environment via:

source honcho/.venv/bin/activate
  1. Set up a database

Honcho utilizes Postgres for its database with pgvector. An easy way to get started with a postgres database is to create a project with Supabase

Alternatively, a docker-compose template is available with a sample database configuration. To use Docker:

cp docker-compose.yml.example docker-compose.yml
docker compose up -d database
  1. Edit the environment variables

Honcho uses a .env file for managing runtime environment variables. A .env.template file is included for convenience. Several of the configurations are not required and are only necessary for additional logging, monitoring, and security.

Below are the required configurations:

DB_CONNECTION_URI= # Connection uri for a postgres database (with postgresql+psycopg prefix)

# LLM Provider API Keys
LLM_GEMINI_API_KEY= # API Key for Google Gemini (used for deriver, summary, and dialectic minimal/low by default)
LLM_ANTHROPIC_API_KEY= # API Key for Anthropic (used for dialectic medium/high/max and dream by default)
LLM_OPENAI_API_KEY= # API Key for OpenAI (used for embeddings when EMBED_MESSAGES=true)

Note that the DB_CONNECTION_URI must have the prefix postgresql+psycopg to function properly. This is a requirement brought by sqlalchemy

The template has the additional functionality disabled by default. To ensure that they are disabled you can verify the following environment variables are set to false:

AUTH_USE_AUTH=false
SENTRY_ENABLED=false

If you set AUTH_USE_AUTH to true you will need to generate a JWT secret. You can do this with the following command:

python scripts/generate_jwt_secret.py

This will generate a JWT secret and print it to the console. You can then set the AUTH_JWT_SECRET environment variable. This is required for AUTH_USE_AUTH:

AUTH_JWT_SECRET=<generated_secret>
  1. Run database migrations

With the database set up and environment variables configured, run the migrations to create the necessary tables:

uv run alembic upgrade head

This will create all tables for Honcho including workspaces, peers, sessions, messages, and the queue system.

  1. Launch Honcho

With everything set up, you can now launch a local instance of Honcho. In addition to the database, two components need to be running:

Start the API server:

uv run fastapi dev src/main.py

This is a development server that will reload whenever code is changed.

Start a background worker (deriver):

In a separate terminal, run:

uv run python -m src.deriver

The deriver generates representation, summaries, peer cards, and manages dreaming tasks. You can increase the number of deriver's to improve runtime efficiency.

Pre-commit Hooks

Honcho uses pre-commit hooks to ensure code quality and consistency across the project. These hooks automatically run checks on your code before each commit, including linting, formatting, type checking, and security scans.

Installation

To set up pre-commit hooks in your development environment:

  1. Install pre-commit using uv
uv add --dev pre-commit
  1. Install the pre-commit hooks
uv run pre-commit install \
    --hook-type pre-commit \
    --hook-type commit-msg \
    --hook-type pre-push

This will install hooks for pre-commit, commit-msg, and pre-push stages.

What the hooks do

The pre-commit configuration includes:

  • Code Quality: Python linting and formatting (ruff), TypeScript linting (biome)
  • Type Checking: Static type analysis with basedpyright
  • Security: Vulnerability scanning with bandit
  • Documentation: Markdown linting and license header checks
  • Testing: Automated test runs for Python and TypeScript code
  • File Hygiene: Trailing whitespace, line endings, file size checks
  • Commit Standards: Conventional commit message validation

Manual execution

You can run the hooks manually on all files without making a commit:

uv run pre-commit run --all-files

Or run specific hooks:

uv run pre-commit run ruff --all-files
uv run pre-commit run basedpyright --all-files

Docker

As mentioned earlier a docker-compose template is included for running Honcho. As an alternative to running Honcho locally it can also be run with the compose template.

The docker-compose template is set to use an environment file called .env. You can also copy the .env.template and fill with the appropriate values.

Copy the template and update the appropriate environment variables before launching the service:

cd honcho
cp .env.template .env
# update the file with openai key and other wanted environment variables
cp docker-compose.yml.example docker-compose.yml
docker compose up

Deploy on Fly

The API can also be deployed on fly.io. Follow the Fly.io Docs to setup your environment and the flyctl.

A sample fly.toml is included for convenience.

Note: The fly.toml does not include launching a Postgres database. This must be configured separately

Once flyctl is set up use the following commands to launch the application:

cd honcho
flyctl launch --no-deploy # Follow the prompts and edit as you see fit
cat .env | flyctl secrets import # Load in your secrets
flyctl deploy # Deploy with appropriate environment variables

Configuration

Honcho uses a flexible configuration system that supports both TOML files and environment variables. Configuration values are loaded in the following priority order (highest to lowest):

  1. Environment variables
  2. .env file (for local development)
  3. config.toml file
  4. Default values

Using config.toml

Copy the example configuration file to get started:

cp config.toml.example config.toml

Then modify the values as needed. The TOML file is organized into sections:

  • [app] - Application-level settings (log level, session limits, embedding settings, namespace)
  • [db] - Database connection and pool settings
  • [auth] - Authentication configuration
  • [cache] - Redis cache configuration
  • [llm] - LLM provider API keys and general settings
  • [deriver] - Background worker settings and representation configuration
  • [peer_card] - Peer card generation settings
  • [dialectic] - Dialectic API configuration with per-level reasoning settings
  • [summary] - Session summarization settings
  • [dream] - Dream processing configuration (including specialist models and surprisal settings)
  • [webhook] - Webhook configuration
  • [metrics] - Prometheus pull-based metrics
  • [telemetry] - CloudEvents telemetry for analytics
  • [vector_store] - Vector store configuration (pgvector, turbopuffer, or lancedb)
  • [sentry] - Error tracking and monitoring settings

Using Environment Variables

All configuration values can be overridden using environment variables. The environment variable names follow this pattern:

  • {SECTION}_{KEY} for top-level section settings
  • Use __ inside {KEY} for nested settings
  • Just {KEY} for app-level settings

Examples:

  • DB_CONNECTION_URI - Database connection string
  • AUTH_JWT_SECRET - JWT secret key
  • DERIVER_MODEL_CONFIG__TRANSPORT - Transport for the background deriver
  • SUMMARY_MODEL_CONFIG__MODEL - Summary model override
  • DIALECTIC_LEVELS__low__MODEL_CONFIG__MODEL - Model for low reasoning level
  • LOG_LEVEL - Application log level
  • METRICS_ENABLED - Enable Prometheus metrics
  • TELEMETRY_ENABLED - Enable CloudEvents telemetry

Configuration Priority

When a configuration value is set in multiple places, Honcho uses this priority:

  1. Environment variables - Always take precedence
  2. .env file - Loaded for local development
  3. config.toml - Base configuration
  4. Default values - Built-in defaults

This allows you to:

  • Use config.toml for base configuration
  • Override specific values with environment variables in production
  • Use .env files for local development without modifying config.toml

Example

If you have this in config.toml:

[db]
CONNECTION_URI = "postgresql+psycopg://localhost/honcho_dev"
POOL_SIZE = 10

You can override just the connection URI in production:

export DB_CONNECTION_URI="postgresql+psycopg://prod-server/honcho_prod"

The application will use the production connection URI while keeping the pool size from config.toml.

Architecture

The functionality of Honcho can be split into two different services: Storage and Insights.

Peer Paradigm

Honcho uses an entity-centric model where both users and agents are represented as "peers". This unified approach enables:

  • Multi-participant sessions with mixed human and AI agents
  • Configurable observation settings (which peers observe which others)
  • Flexible identity management for all participants
  • Support for complex multi-agent interactions

Key Features

  • Rich Reasoning System: Multiple implementation methods that extract conclusions from interactions and build comprehensive representations of peers
  • Chat API: Provides reasoning-informed responses that integrate conclusions with current context
  • Background Processing: Asynchronous processing pipeline for expensive operations like representation updates and session summarization
  • Multi-Provider Support: Configurable LLM providers for different use cases

Storage

Honcho contains several different primitives used for storing application and peer data. This data is used for managing conversations, modeling peer identity, building RAG applications, and more.

The philosophy behind Honcho is to provide a platform that is peer-centric and easily scalable from a single user to a million.

Below is a mapping of the different primitives and their relationships.

Workspaces
├── Peers ←──────────────────┐
│   ├── Sessions             │
│   └── Collections          │
│       └── Documents        │
│                            │
│                            │
└── Sessions ←───────────────┤ (many-to-many)
    ├── Peers ───────────────┘
    └── Messages (session-level)

Relationship Details:

  • A Workspace contains multiple Peers
  • Peers and Sessions have a many-to-many relationship (peers can participate in multiple sessions, sessions can have multiple peers)
  • Messages can exist at two levels:
    • Session-level: Communication between peers within a session
  • Collections belong to specific Peers
  • Documents are stored within Collections

Users familiar with APIs such as the OpenAI Assistants API will be familiar with much of the mapping here.

Workspaces

This is the top level construct of Honcho. Developers can register different Workspaces for different assistants, agents, AI enabled features, etc. It is a way to isolate data between use cases and provide multi-tenant capabilities.

Peers

Within a Workspace everything revolves around a Peer. The Peer object represents any participant in the system - whether human users or AI agents. This unified model enables complex multi-participant interactions.

Sessions

The Session object represents a set of interactions between Peers within a Workspace. Other applications may refer to this as a thread or conversation. Sessions can involve multiple peers with configurable observation settings.

Messages

The Message represents an atomic data unit that can exist at two levels:

  • Session-level Messages: Communication between peers within a session context

All messages are labeled by their source peer and can be processed asynchronously to update their representations. This flexible design allows for both conversational interactions and broader data ingestion for personality modeling.

Collections

At a high level a Collection is a named group of Documents. Developers familiar with RAG based applications will be familiar with these. Collections store vector embedded data that developers and agents can retrieve against using functions like cosine similarity.

Collections are also used internally by Honcho while creating representations of peers.

Documents

As stated before a Document is vector embedded data stored in a Collection.

Reasoning

The reasoning functionality of Honcho is built on top of the Storage service. As Messages and Sessions are created for Peers, Honcho will asynchronously reason about peer psychology to derive facts about them and store them in reserved Collections.

A high level summary of the pipeline is as follows:

  1. Messages are created via the API
  2. Derivation Tasks are enqueued for background processing including:
    • representation: To update representations of Peers
    • summary: To create summaries of Sessions
  3. Session-based queue processing ensures proper ordering
  4. Results are stored internally

Retrieving Data & Insights

Honcho exposes several different ways to retrieve data from the system to best serve the needs of any given application.

Get Context

In long-running conversations with an LLM, the context window can fill up quickly. To address this, Honcho provides a context endpoint that returns a combination of messages, conclusions, summaries from a session up to a provided token limit.

Use this to keep sessions going indefinitely. If you'd like to see this in action, try out Honcho Chat.

There are several search endpoints that let developers query messages at the Workspace, Session, or Peer level using a hybrid search strategy.

Requests can include advanced filters to further refine the results.

Chat API

The flagship interface for using these insights is through the Chat Endpoint.

This is a regular API endpoint (/peers/{peer_id}/chat) that takes natural language requests to get data about the Peer. This robust design lets us use this single endpoint for all cases where extra personalization or information about the Peer is necessary.

A developer's application can treat Honcho as an oracle to the Peer and consult it when necessary. Some examples of how to leverage the Dialectic API include:

  • Asking Honcho for a generic or specific insight about the Peer
  • Asking Honcho to hydrate a prompt with data about the Peers behavior
  • Asking Honcho for a 2nd opinion or approach about how to respond to the Peer
  • Getting personalized responses that incorporate long-term facts and context

Representations

For low-latency use cases, Honcho provides access to a representation endpoint that returns a static document with insights about a Peer in the context of a particular session.

Use this to quickly add context to a prompt without having to wait for an LLM response.

Contributing

We welcome contributions to Honcho! Please read our Contributing Guide for details on our development process, coding conventions, and how to submit pull requests.

License

Honcho is licensed under the AGPL-3.0 License. Learn more at the License file