On this page
2.0.0 adds the HippoDb engine features the SDK could not reach before (asking what was true at a past moment, choosing a retrieval plan, deleting edges and fabrics), makes the SDK work behind the HippoDb manager with API keys, bounds what an LLM call carries (tools and history), lets a chat choose how hard a reasoning model thinks, lets a frontend stop a running chat, and removes the code that depended on engine routes that no longer exist. Several write calls that used to discard what the engine told them now return it.
This document explains what is new, how to upgrade from 1.x, and then gives an overview of what the SDK
does as a whole. The reference documents are listed at the end. For the exhaustive list of changes see
CHANGELOG.md in the repository root.
Charter and Curator, two engine features, are not supported by this SDK and there is no SDK API for them.
What is new#
Ask what was true at a past moment#
think() takes an as_of argument and rebuilds the memory as it stood at that instant.
now = await hippo.think("Checkout bug")
then = await hippo.think("Checkout bug", as_of="2026-09-15")
then.as_of["instant"] # "2026-09-15T00:00:00Z"
then.as_of["doesNotReconstruct"]
What it does and does not do:
- It uses the real time each concept was written and each fact changed. It never reads dates written in the text of a conversation, and nothing can be back-dated. "As of 15 September" typed into a chat message is not something the engine can interpret; the caller has to pass the date.
- It reconstructs concepts, edges (including ones since removed or merged away) and attribute values. Edge weights are always today's weights; there is no weight history.
as_ofaccepts a full ISO-8601 instant, a bare date (read as midnight UTC) or a timestamp with no zone (read as UTC).ThinkResult.as_ofcarries the engine's own statement of what was and was not reconstructed, so a historical answer is never mistaken for a current one.
temporal_direction="BACKWARD" or "FORWARD" limits spreading activation to one side of a point in time
("what led up to X", "what followed from X").
The memory_think tool the LLM sees accepts both arguments. as_of is the moment a memory was stored,
not a date inside what it says: for data written long after the events it describes (an import, a
back-fill), an event date earlier than the day the data was written returns nothing, because nothing existed
yet. The tool description tells the model this, and the engine's caveat is returned with the result,
including when a memory formatter is in use.
Choose the retrieval plan#
think(plan=...) sends an explicit plan. ThinkResult.plan always reports the plan the engine ran, whether
you chose it or its planner did.
result = await hippo.think("Checkout bug", plan="exact > spread(2) > reserve(0.4)")
result.plan # "resolve_exact > spread(2) > reserve(0.4)"
Steps are joined with > and are case-insensitive: exact, lexical, semantic, temporal, tag,
spread(n), collapse, reserve(frac), deep(frac), diversify(n), limit(n). The names in
ThinkResult.plan (resolve_exact, ...) are the engine's output form and are not accepted as input.
Omitting plan gives the engine's default behavior. The SDK does not validate a plan; the engine answers
HTTP 400 for an unknown step. The memory_think tool does not expose plan.
Delete edges and fabrics#
await hippo.delete_edge("Task 1", "Task 2") # every edge between the pair
await hippo.delete_edge("Task 1", "Task 2", edge_type="PRECEDES") # one type only
await hippo.delete_edges([{"from": "A", "to": "B"}, {"id": "e-7"}], ignore_missing=True)
await hippo.delete_edge_by_id("e-7")
await hippo.delete_fabric("scratch") # permanent
- Edge deletion is a soft delete. The edge disappears from
graph(), butthink(as_of=...)can still reconstruct it for a time before the delete. - Without
edge_type, every edge between the two concepts is removed.cascade_inverse(default on) also removes the paired inverse edge, for exampleCATEGORY_INCLUDESfor anIS_A. - Two real concepts with no edge between them is not an error: the call succeeds with
deletedCount0. An unknown concept is an HTTP 404 listingnotFound, unlessignore_missing=True. - Batch deletion validates everything first and deletes nothing if any selector cannot be resolved, unless
ignore_missing=True. delete_fabric()removes the fabric's database, search index and data files. There is no undo and no "empty it but keep it". There is still no way to delete a single concept.
Work behind the HippoDb manager#
In production the engine sits behind a manager that authenticates with API keys. HippoClient now sends
Authorization: Bearer <key>:
HippoClient(base_url="https://hippodb.example.com", fabric="my_agent", api_key="hdb_live_...")
- Where the key comes from. The
api_keyargument, else theHIPPODB_API_KEYenvironment variable.AgentRunnerreads it from the environment or the agent's.env(the newAgentSettings.hippodb_api_key), passes it to its client, and also exports it asHIPPODB_API_KEY(unless already set) so aHippoClientbuilt later in the same process without a key still sends it. - A host that builds
HippoClientitself must passapi_key=. A key that only lives in its own.envis not in the process environment, so the fallback does not see it. - A manager in enforce mode answers 401 to every request without a valid key (the body's
errorsays which:missing_credential,invalid_credential, ...) and 403 to a key without the needed scope. Only the manager's own health probe,/admin/manager/health, is open. The key needs the scopesfabric:read,fabric:writeandfabric:delete, and a fabric cap (max_fabrics, 25 by default) that fits your users. - No key sends no header, which still works against a standalone engine or a manager in permissive mode.
- Everything the SDK sends carries the key. The
BRAIN_SCANandBRAIN_CONCEPTScontrol commands and thebrain_reportcommand (new--api-keyoption, orHIPPODB_API_KEY) used raw HTTP calls without it and could not work against an enforcing manager; they now useHippoClient. - The SDK also copes with the manager listing fabrics as plain names, which used to crash fabric-loss
detection, and
list_fabrics()now returns dicts against both.
Help discovery find your tools#
A tool can now say what discovery cannot guess from its name. All four attributes are optional and none of them is sent to the model:
class CartAdd(BaseTool):
name = "cart_add"
description = "Add an item to the cart"
domain = "shopping" # linked with every tool in this domain, not with "cart_*"
related = ("checkout_pay",) # often used together with this one
keywords = ("basket", "trolley") # synonyms the name and description lack
examples = ("put the blue shoes in my basket",) # things a user might say
memory_think also stops returning tool-routing concepts (TOOL, INTENT, WORKFLOW) next to the user's own
memory, and the agent, memory and gateway logs now rotate (LOG_MAX_BYTES, LOG_BACKUP_COUNT) instead of growing
without limit. memory.log is also quieter: it holds one line per HippoDb call (think, query, ingest, link) with the
turn, fabric and the fields worth grepping, instead of the whole request and response as pretty-printed JSON. In a
small test the same calls took 3 KB and 26 lines instead of 16 KB and 402. MEMORY_LOG_PAYLOADS=true keeps the full
bodies in memory.log; the agent log keeps them at DEBUG either way.
More robust HippoDb calls#
HippoClient takes timeout, connect_retries and transport. A request whose connection cannot be opened
is retried twice with a short, jittered backoff; nothing else is retried, because only a connect failure
guarantees the server saw nothing (so writes are safe). The default timeouts are unchanged.
Stop a running chat#
A frontend "stop" button used to do nothing useful on the backend: the LLM call ran in a worker thread that could not be cancelled, so the call finished and billed after the client had gone.
agent.stop(conversation_id)ends the running turn gracefully. It aborts an in-flight LLM call, lets a tool that is already running finish (it is never interrupted), skips the rest, saves the turn so far in history, and makeschat()return the text produced so far.agent.last_turn.statusis then"stopped".- Cancelling the task that runs
chat()(a disconnect, a timeout) now cancels the LLM call as well. The SDK awaitslitellm.acompletionon your event loop, so this works for every provider LiteLLM supports. - A turn that is cut short is remembered. If it had already run tools, it stays in history with a result for
every tool call and a closing marker, so the next turn does not repeat the same writes. Mark a tool class
atomic = Trueif it must finish even when the turn is cancelled. - A new
turn_endevent closes every turn with itsstatus, andagent.last_turnhas the same information.
See Events and Streaming.
Cheaper tool-using turns: prompt caching#
A turn can use up to 20 LLM rounds, and each round resends the same tools, system prompt and conversation. For
Anthropic models the SDK now marks that repeated prefix as cacheable (LLM_PROMPT_CACHING, on by default), so
later rounds read it at a fraction of the normal input price. Providers that cache automatically (OpenAI, Gemini,
DeepSeek, xAI) need nothing from the SDK; the stable tool order helps them too. Cache usage appears in the log
line and the llm_response event (cached_tokens, cache_write_tokens). See
LLM Routing.
Transient LLM failures (rate limits, 503 and other server errors, connection errors) are now retried with jittered
backoff (LLM_MAX_RETRIES, default 2), where only an "overloaded" error was retried before.
Keep the prompt bounded: tools and history#
Every tool definition costs about 1.2k tokens and is sent again on every LLM round. Before 2.0.0 only the discovery result was capped (12), so the list could grow without limit (one deployment saw 33, then 45).
- Tool limits. One call carries at most 35 definitions by default: 13 always-on, 12 discovered, 5 carried
over from earlier turns and 5 added mid-turn by
discover_more_tools. Carried tools that do not fit are dropped least recently used first; always-on and discovered tools are never dropped. SetMAX_TOTAL_TOOLS,MAX_CARRIED_TOOLSandMAX_MID_TURN_TOOLS, orTOOL_LIMITS_ENABLED=falseto remove the limits. When nothing matches adiscover_more_toolsrequest it now adds nothing, where it used to add every remaining tool. - History window. The default
history_windowis now 5 turns, down from 20. Each stored turn keeps its full tool trace, so 20 turns could make a very large prompt. The conversations preloaded at session start count as one of the turns; older material is recalled from HippoDb withmemory_think. SetHISTORY_WINDOW(orBaseAgent(history_window=)) if you need more.
Typed LLM errors#
A failed LLM call now raises an LlmError subclass instead of LiteLLM's own exception: LlmRateLimitError,
LlmOverloadedError, LlmConnectionError, LlmTimeoutError, LlmAuthError, LlmContextWindowError and
LlmBadRequestError. Each has model, provider, status_code, retry_after (from the provider's
Retry-After header) and retryable, and the LiteLLM exception is its __cause__. A host can wait and retry on
a rate limit, ask the user to shorten the conversation on a context-window error, and alert an operator on an
auth error, without importing LiteLLM or reading message text. The SDK still retries rate limits, overload and
connection errors itself first (LLM_MAX_RETRIES, default 2).
Reasoning effort, per message#
A chat UI can now let the user choose how hard a reasoning model thinks. agent.chat(message,
reasoning_effort="high") takes low, medium or high for one message, "off" turns the agent's default off for
that message, and LLM_REASONING_EFFORT (or BaseAgent(reasoning_effort=...)) sets the default. LiteLLM maps it for
Claude, OpenAI's reasoning models, Gemini and DeepSeek. agent.supports_reasoning_effort() says whether to show the
control, and agent.last_turn.reasoning_effort says what a turn used. The SDK makes it work with tools: it adds room
for the thinking to the output limit (Anthropic rejects high otherwise) and keeps the signed thinking blocks with the
tool calls of the turn in progress, then drops them from the stored history. Checked against the real Anthropic API on
Claude Haiku 4.5 and Claude Sonnet 5.5, with and without streaming. The newest Claude models need LiteLLM 1.104 or newer
for this, so the SDK now requires litellm>=1.104.2. See LLM Routing.
Writes report what happened#
learn()returns the real result: the label as the engine resolved it (an identity merge can land the write on a different existing label),type,identity_status,facts_set,facts_supersededandrecent_similar.update_concept()used to make no request at all. It now writes throughingest()and returns the resolvedlabel,facts_set,facts_supersededandidentity_status.
Fixes that change behavior you may have worked around#
ToolDiscovery.discover()now indexes the registered tools itself. A host that builtBaseAgentdirectly, withoutAgentRunner, never indexed its tools and discovery silently found no business tools. After the first call per (engine URL, fabric) this costs nothing.index_tools()raisesFabricNotFoundErrorwhen the fabric is gone, instead of logging it and recording the fabric as indexed.- Tools added in a later release are now found in existing fabrics.
index_tools()used to check only the first tool to decide a fabric was already indexed. A tool added later was never learned but was still linked, which made the engine create it as a plain concept that discovery cannot find, and the engine cannot retype it afterwards. Indexing now compares the registry with the fabric by name, learns what is missing, and links only real tool concepts. A tool whose name is contained in another concept's label (for exampleorder_listandrecurring_order_list, or a user's own concept) is also no longer merged into it; it is reported in the log and inToolDiscovery.last_index_report. A fabric where an older SDK already created such a plain concept is repaired on the next start: the tool is learned again and checked, and listed inIndexReport.repaired. This needs an engine that fills in a missing type on ingest; on any other engine, and for a concept typedCONCEPT, the tool stays untyped, is listed inIndexReport.untyped, and a warning names it (use a fresh fabric then). - Edits to a tool reach existing fabrics. A longer
description, newkeywordsor newexamplesare written to a tool that was indexed earlier (the engine replaces a stored description only with a longer one and merges the tags).keywordsnow also go into the stored description, not only the tags. Reported inIndexReport.refreshed. - A seed no longer hides the tools it mentions. The seed was loaded before the tools were indexed, and a
link to a tool that does not exist yet makes the engine create a plain, untyped concept.
Every tool named in a seed's bridges or workflows was therefore invisible to discovery. The seed is now loaded
after the tools are indexed (whether the fabric is fresh is still checked first).
load_seed()also creates aTOOLconcept for every tool it names before it links anything, so it is safe to call on its own. - Plus several smaller fixes: an image from a failed
chat_with_image()no longer leaks into later turns, the tools array is sent in a fixed order, tools that were offered but never used keep their three turns of grace from the turn they were discovered, discovery logs which tools it found, and a tool error with no message now carries the exception type. TOOLS_SYNC(the Connector Hub's tool-allocation command) no longer removes your own tools. It used to unregister every tool without a built-in name prefix that the Hub had not allocated, which meant the first sync deleted all business tools anddiscover_more_tools. It now manages only the Hub tools it created, ignores a request withoutallocated_tools, does nothing when the Hub catalog cannot be fetched, and keeps a local tool when a Hub tool has the same name. Only agents with networking enabled were affected.- The
memory_thinkdate pre-filter (date=2026-03-15,month=2026-03) was calling a method on an attribute that does not exist; the error was swallowed and the search fell back to the raw date string. It now queries the timeline as intended.
Upgrading from 1.x#
Most 1.x code keeps working. These are the places that can break, in the order you are likely to meet them.
| If your code... | You will see | Do this |
|---|---|---|
passes depth= to HippoClient.query() |
TypeError: unexpected keyword argument 'depth' |
Drop it. The engine ignored it. Use think(steps=...) for multi-hop questions |
passes dream_prompt= to RoleConfig |
TypeError |
Drop it. Its only consumer was the removed dream route |
imports hippodb_agent.tuning or RequestTuning |
ImportError |
Remove the import. The tool was not in the default tool set and failed on nearly every call |
lists memory_dreams or request_tuning in role prompts or scopes |
the tool no longer exists | Remove the mentions |
| calls any of the 18 removed-route methods (below) | EngineCapabilityRemovedError |
Remove the call. There is no replacement |
catches httpx.HTTPStatusError around those calls |
the new error is not an httpx error |
Catch EngineCapabilityRemovedError (a HippoDbError), or remove the call |
reads learn(...)["id"] |
KeyError |
Use ["label"]. The engine addresses concepts by label; "id" was always "" |
imports hippodb_agent.feedback (classify_feedback, FeedbackType) |
ImportError |
Remove the import. The classifier was a standalone keyword matcher that nothing in the SDK called or acted on |
imports NeuroMonitor, MemoryHealthSnapshot or any metric event class from hippodb_agent.monitor |
ImportError |
Remove them; they recorded removed features and nothing called them. brain_report is unchanged apart from dropping its crystallization, co-activation, SQL-pattern and prompt-template sections |
reads settings.brain_capacity |
AttributeError |
Remove it. Nothing used it, and capacity is set by the engine |
imports anthropic and relied on the SDK installing it |
ModuleNotFoundError |
Add anthropic to your own dependencies; the SDK never imported it |
calls delete_edge() |
edges are now actually deleted | It used to do nothing. Review every call site |
| pins LiteLLM below 1.104.2 | the install fails to resolve | The SDK now requires litellm>=1.104.2. Reasoning effort on the newest Claude models fails with older versions, and the SDK's tests run on 1.104.2 |
iterates the result of list_fabrics() as names (against a manager) |
each item is now a dict, {"name": ...} |
Read f["name"]. The engine already returned dicts, and the method is now the same against both |
relies on the default history_window of 20 |
the model sees the last 5 turns | Set HISTORY_WINDOW=20 (or BaseAgent(history_window=20)) to keep the old window |
catches litellm.RateLimitError (or another LiteLLM exception) around chat() |
the exception is not caught: you get LlmRateLimitError |
Catch the matching Llm...Error, or LlmError for all of them. The LiteLLM exception is its __cause__ |
uses tool_scopes=[] |
every non-builtin tool is hidden | Unchanged, now documented: use a prefix list, or None at the registry for no restriction |
The 18 removed-route methods raise immediately, without sending a request: consolidate,
consolidate_light, consolidate_tier1, consolidate_tier2, consolidate_tier3, consolidation_status,
promote, belief_contested, belief_profile, belief_revise, belief_acknowledge, belief_audit,
dream, get_dreams, init_clusters, sleep_enter, sleep_wake, sleep_status. The engine retired
these route families for good; they were built, measured and removed, and are not coming back. They are
kept as methods so imports resolve and the failure is loud and named instead of a bare 404 or a fake
success. For init_clusters(), create cluster hubs by passing clusters on the concepts you ingest().
experience(), detect_crosslinks() and auto_crosslink() remain harmless no-ops. Automatic linking is
now done by the engine itself (SIMILAR_TO and RELATED_TO edges), and the CONTRADICTS and DISPUTES
edge types no longer exist.
Host applications
- If the engine is behind a manager with enforced keys, set
HIPPODB_API_KEYor passapi_key=. AgentRunnerno longer creates an_evolutionfabric at startup. One created by an earlier version is left in place. The engine keeps every fabric loaded in memory, so once you have confirmed nothing else uses it you can free it withawait hippo.delete_fabric("_evolution").- If you catch
FabricNotFoundErrorto rebuild a session, it can now also come out ofdiscover()andindex_tools().
What the SDK does#
Running an agent#
AgentRunner is the one-line entry point. It connects to HippoDb, creates or reuses the agent's fabric,
seeds it, builds the tool registry, wires safety and memory features, and starts a terminal session.
from hippodb_agent import AgentRunner, RoleConfig, BaseTool
runner = AgentRunner(
role=RoleConfig(name="hr", display_name="HR Assistant", tool_scopes=["hr_"],
fabric="hr_agent", system_prompt="You are an HR assistant.\n\n{manifest}"),
business_tools=[ListEmployees],
api_base_url="http://localhost:9000", # or backends={"hr": "...", "payroll": "..."}
seed_file="seed.yaml",
)
runner.start()
AgentRunner runs a terminal session. A web or API host builds the parts itself and calls
BaseAgent.chat(message, conversation_id=..., reasoning_effort=...) for each message; the guide
Building an Agent Without AgentRunner has a complete, tested example and the
settings to pass. RoleConfig defines identity, prompt, tool scopes and always-on tools; the {manifest}
placeholder is replaced with memory context at runtime. A safety_header on the role is always prepended and
cannot be overridden by templates.
Per-conversation history is kept per conversation_id, capped at history_window turns (default 5, was 20), and
stores full tool traces. Optional text streaming (enable_streaming) relays model text through the
agent's event_queue (see docs/technical/events-and-streaming.md), and chat_with_image() accepts an image
alongside text.
Memory in HippoDb#
Every agent has its own HippoDb fabric: a graph of concepts, facts, timeline events and weighted edges.
- Write with
ingest()(concepts with nested facts, timeline events, tags and cluster membership) or thememory_remembertool. A new fact for an existing attribute supersedes the old value. - Read with
think()(spreading activation; cluster-aware throughmemory_think),query()(routes through semantic search, facts and timeline),facts(),timeline()andlist_concepts(). - Identity. The engine can detect duplicate concepts and merge them, or file a conflict when it
cannot decide. The SDK surfaces this:
recent_similarhints on writes,memory_list_conflictsandmemory_resolve_conflicttools, andidentity_statuson recalled concepts.skip_identity_check=Trueskips the pass for curated batches. - Pre-education. A
seed.yaml(domain concepts, intents, concept-to-tool bridges, tool workflows and starter rules) is loaded once into a fresh fabric, so the agent does not start with an empty graph. Seedocs/technical/pre-education.md. - Conversation continuity. Every exchange is logged, and the most recent ones (
session_context_preload, default 5) are loaded at session start. Reads and writes are written to a turn-correlated audit log. - Formatting. THINK results are presented to the LLM as
structured,narrative,xmlorrawoutput within a token budget (memory_format,memory_format_max_tokens), or through your ownBaseMemoryFormatter.
Tools#
Business tools subclass BaseTool and call a backend through self.api (or self.apis["name"] with
several backends). The SDK adds built-in memory tools, OS tools and calculator tools.
- Tool discovery. With many tools, sending every schema each turn is expensive and unreliable. Tools
are stored as
TOOLconcepts in memory, and each turn HippoDb's spreading activation selects the relevant ones (discovery_max_tools, default 12) plus an always-on set. The model can calldiscover_more_toolswhen the selection is not enough. A small set of enterprise tools can bypass discovery entirely (enterprise_always_on_threshold). - Tool limits. One LLM call carries at most 35 tool definitions by default (see "Keep the prompt
bounded" above).
MAX_TOTAL_TOOLS,MAX_CARRIED_TOOLSandMAX_MID_TURN_TOOLSset the numbers, andTOOL_LIMITS_ENABLED=falseturns the limits off. - Scopes.
tool_scopesrestricts business tools to name prefixes. The built-ins (thememory_,os_,calc_andnetwork_prefixes anddiscover_more_tools) are always in scope. An empty list hides every non-builtin tool; it does not mean "no restriction". - Always-on tools. Add your own with
RoleConfig.always_on_tools.
Rules#
- Soft rules are
RULEconcepts recalled before a business tool runs and shown to the model as guidance. The model can create and retire them withmemory_learn_ruleandmemory_forget_rule. - Hard rules are natural-language rules compiled by an LLM into a validated rule spec and enforced in
code around the tool call, with no LLM involved at enforcement time. Actions include
require_keyandreject(gate),set_field(before), andset_field,mask_fieldandannotate(after), with a sandboxed Python escape hatch. Newly compiled hard rules wait for explicit approval before enforcing (require_hard_rule_approval, on by default);memory_promote_ruleandmemory_approve_ruledrive that.
Data gateway and compliance#
The gateway sits between a tool's result and the model. It masks PII (built-in patterns plus
per-tool sensitive_fields with redact, keep_last_4 or type_only), summarizes long lists to a few
representative rows (gateway_summary_threshold), and writes an audit trail of what crossed the boundary.
Setting GATEWAY_COMPLIANCE=GDPR (or a comma-separated list) loads that framework's field policies; GDPR,
CCPA, SOX, HIPAA, PCI_DSS, LGPD and DPDP are built in. Each framework also ships compliance principles, which
ComplianceSeedGenerator turns into rules you load yourself; they are not applied automatically. Details and
limits are in docs/technical/compliance.md.
LLM providers and routing#
Models run through LiteLLM, so MODEL=<provider>/<model> works for Anthropic, OpenAI, xAI, Google Gemini
(use the gemini/ prefix), Cohere, Mistral and Ollama. Optional multi-model routing (LLM_ROUTING_MODELS, LLM_ROUTER_MODEL) lets a small
router model pick which model handles each message; see docs/technical/llm-routing.md. llm_call_timeout_s bounds
a single LLM round, which otherwise can hang for LiteLLM's 600-second default.
Agent network#
With network_nats_url set, agents register with a registry, discover each other by capability, send
direct and department-wide messages, and receive enterprise tool allocations over NATS. The network_
tools are always on when networking is enabled. Each agent keeps its own brain; agents exchange messages,
never memory. See docs/technical/agent-network.md.
Everything else#
- Agent Creator (
python -m hippodb_agent.creator): a meta-agent that interviews you, reads an OpenAPI spec and generates a starter project (role.py,tools.py,seed.yaml,main.py,requirements.txtand an.envtemplate). - Prompt composer: assembles the system prompt from the role's
safety_header, body,{manifest}andapp_contextplaceholders. - Standalone utility the runtime does not call: the
brain_reportcommand, which prints a report on a fabric. It is available to host apps, but nothing in the agent loop uses it. - Typed errors:
HippoDbError(base),HippoTimeoutError,FabricNotFoundError,EngineCapabilityRemovedErrorand theLlmErrorfamily (see "Typed LLM errors" above), all importable fromhippodb_agent.
Limits to know about#
These come from the engine, not the SDK, but they shape what you can build.
facts()returns only the current value of an attribute and one previous value. There is no route for the full change history, so "list every status this task had" cannot be answered.- The engine only merges duplicate concepts if it has an LLM configured; without one it never merges. When
it does, the model choice matters: in testing a smaller model made wrong merges, and a larger one hit an
engine bug (empty
thinkingblock parsing) that delays settling. The fix belongs in the engine. - With no embedding model on the engine, search and
thinkseeding are lexical, and an off-topicquery()returns nothing. - The identity log and think traces live in engine memory and are lost on restart.
- Every fabric stays loaded in the engine for its lifetime, so memory grows with the number of fabrics.
Compatibility#
- Python 3.12 or newer.
- LiteLLM 1.104.2 or newer (installed with the SDK).
- The calls that use newer engine features (
as_of,plan, edge and fabric deletion) need an engine that has them; otherwise they fail with the engine's own error. - The 18 removed-route methods fail locally, whatever engine you run.
How this was tested#
The SDK's automated tests (nearly 600) cover each feature above. The engine-facing calls were also run against a
live HippoDb engine and through the manager with API keys enforced: think() with as_of, temporal_direction
and plan, learn(), update_concept(), edge and fabric deletion, the removed routes, key passing and the
brain_report command. Reasoning effort, tool loops and streaming were run against the live Anthropic API on
Claude Haiku 4.5 and Claude Sonnet 5.5. Not run live: engines with an LLM configured for identity decisions, and
the agent network.
Reference documents#
- Building an Agent Without AgentRunner: web and API hosts, with a complete example
- Technical Reference: every module, class and setting
- LLM Routing: models, keys, routing, retries, typed errors, prompt caching, reasoning effort
- Events and Streaming: the event queue, stopping a turn
- Pre-Education: seed files
- Compliance: the data gateway and compliance frameworks
- Agent Network: NATS messaging between agents