SessionService path is intentionally not enough. This page covers expert-level direct agent construction, provider configuration, budgets, hook helpers, and lower-level delivery internals.
Runtime-backed vs standalone builds
The Rust contract is explicit:- runtime-backed surfaces should call
MeerkatMachine::prepare_bindings(session_id) - those bindings should be threaded through
SessionBuildOptions.runtime_build_mode = RuntimeBuildMode::SessionOwned(bindings) - standalone/testing/embedded paths should use
RuntimeBuildMode::StandaloneEphemeral
AgentBuilder vs AgentFactory
meerkat::AgentBuilder is the public facade builder. It accepts explicit client/tool/store overrides for embedded use, then still routes through AgentFactory::build_agent() so provider defaults, session metadata, hook wiring, and runtime build-mode defaults stay aligned with the factory path.
AgentFactory (in the meerkat facade) is the opinionated composition layer. It knows about tool categories, runtime resources, comms, memory, mobs, and skills, and wires them into the dispatcher before passing them to AgentBuilder. All public surfaces go through the runtime-backed session path built on top of AgentFactory.
The lower-level meerkat_core::AgentBuilder is not re-exported by the facade. Its standalone build path is reserved for core tests; public embedding code should use the facade builder or AgentFactory.
Use AgentFactory via build_persistent_service() (main path), build_ephemeral_service() (substrate/testing path), or the public meerkat::AgentBuilder facade unless you explicitly need to bypass session lifecycle orchestration. Direct core builder usage means you own composition, persistence, event handling, and any drift from the standard runtime-backed path.
If you are building a runtime-backed surface around SessionService, avoid the
old hand-rolled register_session() + registry extraction pattern. Prefer the
binding seam above so the runtime/session owner stays canonical.
AgentBuilder
For most use cases, prefer
SessionService via the runtime-backed persistent path (see
overview). The public AgentBuilder delegates to the factory
pipeline. Use the core builder only inside core-owned tests that bypass the
session service and facade composition entirely.All builder methods
All builder methods
Providers
Built-in clients for major LLM providers:- Anthropic
- OpenAI
- Gemini
Provider parameters
Pass provider parameter overrides viaAgentBuildConfig. The JSON bag is retired:
provider_params is the typed ProviderParamsOverride (temperature, top_p,
max_output_tokens, reasoning mode, thinking_budget_tokens, and an optional
provider-specific provider_tag), parsed fail-closed at each surface ingress.
Provider tags also carry provider cache policy: OpenAI can override Responses
store (default remains false) and set prompt_cache_key /
prompt_cache_retention. Factory-built public OpenAI API GPT-5.6 sessions default to
prompt_cache_options: {"mode":"implicit","ttl":"30m"} plus a stable
per-session routing key derived from the durable SessionId; a caller-supplied
key wins. These defaults are not applied automatically to the private ChatGPT
or Azure OpenAI backend wires. prompt_cache_options.mode: "explicit" makes Meerkat author
append-monotone breakpoints at deterministic message boundaries for Responses
and Chat Completions. Set prompt_cache_enabled: false for a durable opt-out; it emits
explicit-only mode without a breakpoint and incurs no cache-write charges.
Keep traffic near OpenAI’s recommended 15 requests per minute per cache key;
partition higher-volume traffic with a stable mapping. Tool-calling agents can
make several model requests during one user turn, so a single tool-heavy turn
can reach that guidance without concurrent users; per-session and per-identity
keys are both subject to the ceiling. Choose and monitor the partition using
the observed model-request rate. Cache reads consider only the latest 50
breakpoints.
Anthropic API, Vertex, and Foundry clients default to
cache_control: automatic, which keeps a moving five-minute breakpoint on the
growing conversation (disabled opts out and system_prefix narrows the
breakpoint). Amazon Bedrock defaults to disabled because it does not support
Anthropic automatic caching and rejects an explicit automatic override
locally; manual system_prefix caching remains available. Automatic lookup
scans backward at most 20 cacheable blocks. Direct AnthropicClientBuilder
users targeting a custom backend must declare whether it supports automatic
caching; the provider runtime handles this for configured backends. Gemini can
pass an explicit cached_content_name. When OpenAI store is explicitly
enabled, stored response IDs may be reused as previous_response_id hints;
Meerkat still keeps the local transcript as the canonical replay source and
falls back to full replay if the provider rejects the hint.
Implementing a custom LLM client
Implementing a custom LLM client
Budget configuration
Retry configuration
When to bypass SessionService
Direct agent construction still makes sense when you need one of these expert-only scenarios:- You are embedding a single transient agent loop with fully custom persistence and tool composition.
- You are testing a lower-level trait contract in isolation from session orchestration.
- You are implementing infrastructure that itself sits underneath a
SessionService.
SessionService so runtime admission, history, interruption, and external-event handling stay canonical.
Hook helpers
Comms delivery and observation
Public comms injection is a delivery API.event_injector() gives you an Arc<dyn EventInjector>, and inject() queues a runtime-backed external event for later admission.
How it works
How it works
inject()queues a plain event into the session inbox.- The runtime-backed surface admits that queued event as future turn work.
- Observation is selected independently:
- use the session’s primary
event_txfor full session activity, - use mob member subscriptions for agent-scoped activity,
- use mob event subscriptions for attributed mob-wide activity.
- use the session’s primary
- Public callers no longer receive an interaction-scoped stream from injection.
- Agent must be in keep-alive mode if you want the keep-alive loop to drain inbox events.
- Comms must be enabled.
- If you need streaming output, configure an observation surface separately.
SSE streaming example
SSE streaming example
Complete example
Python and TypeScript SDKs
Both communicate with a localrkat-rpc subprocess over JSON-RPC 2.0 (with optional explicit realm/instance scoping) — no native bindings required.
- Python: Python SDK overview
- TypeScript: TypeScript SDK overview
See also
- Rust SDK overview - getting started, sessions, events
- Tools and stores - tool system, stores, MCP
- API reference - type index
- Architecture - system design and internals
