Reference
Python API reference
The public surface of replicate_mcp: every exported class
and function, the constructor defaults that govern runtime behaviour, and the full
exception hierarchy.
Everything documented here is re-exported from the top-level package, so a single
import style covers the whole framework: from replicate_mcp import agent, CostAwareRouter,
ResultCache. The package's __all__ is the contract — symbols outside it (such as
AgentExecutor, TokenBucket, and the resilience helpers) are stable but imported
from their submodules, and each is flagged below. Sections follow the request lifecycle:
define agents, compose workflows, route, protect, cache, distribute, extend.
Agents and SDK
An agent is a plain function that builds a Replicate payload, plus metadata used for
routing and MCP tool listings. The @agent decorator registers metadata as a
side effect and returns the function unchanged; AgentBuilder does the same thing
fluently for programmatic setup.
@agent keyword | Default | Description |
|---|---|---|
model | function name | Replicate model path (owner/model). |
description | function docstring | Human-readable description for the MCP tool listing. |
tags | [] | Arbitrary labels for filtering. |
supports_streaming | False | Whether the model supports streaming output. |
estimated_cost | None | Estimated USD cost per invocation. |
input_schema | {} | JSON Schema dict for input validation. |
registry | module default | Target AgentRegistry; defaults to the shared module-level registry. |
AgentBuilder(safe_name) chains .model(), .description(), .tag(*tags),
.streaming(enabled=True), .estimated_cost(usd), .avg_latency(ms), and
.input_schema(schema), then terminates with .build() (returns metadata without
registering) or .register(registry=None) (builds and registers). Both produce an
AgentMetadata dataclass with fields safe_name, description,
input_schema, supports_streaming, model, estimated_cost,
avg_latency_ms, and tags; replicate_model() falls back to
safe_name when model is unset.
AgentRegistry (from replicate_mcp.agents.registry) is the thread-safe store
behind the decorator: register() (raises DuplicateAgentError on conflict),
register_or_update(), remove(), get(), has(), list_agents()
(returns a copy), filter_by_tag(), count, and clear().
AgentContext is a context manager that swaps in an isolated registry and restores
the previous one on exit — use it in tests so decorator registrations do not leak.
AgentExecutor (from replicate_mcp.agents.execution) runs registered agents
with streaming, concurrency capping, per-model circuit breakers, and retries. Its
run(agent_id, payload) method is an async generator of chunk dicts;
resolve_model(agent_id) maps a short name to a model path, and
circuit_breaker(model_id) returns the breaker guarding a model.
AgentExecutor argument | Default | Description |
|---|---|---|
model_map | built-in map | Short-name to model-path mapping; copies DEFAULT_MODEL_MAP when unset. |
api_token | env var | Falls back to REPLICATE_API_TOKEN. |
max_concurrency | 10 | Semaphore cap on simultaneous Replicate calls. |
max_retries | 2 | Retry attempts per call. |
retry_base | 0.5 | Base back-off delay in seconds. |
circuit_breaker_config | defaults | CircuitBreakerConfig shared by all per-model breakers. |
rate_limiter | None | Optional TokenBucket throttling all calls. |
observability | None | OpenTelemetry facade for traces and metrics. |
plugin_registry | None | Plugins whose hooks run around each invocation. |
audit_logger | None | Records every invocation to the local audit log. |
cache | None | Optional ResultCache; caching is off by default. |
Workflows
A workflow is an ordered list of agent steps where each step's output feeds the next.
WorkflowBuilder(name) chains .description(text) and
.then(agent_name, input_map=None, condition=None), then .build() returns an
immutable WorkflowSpec (fields name, description, steps; properties
step_count and agent_names). Building with zero steps raises
ReplicateMCPError.
| Function | Description |
|---|---|
register_workflow(spec) | Adds a WorkflowSpec to the module-level registry and returns it; required before replicate-agent workflows run NAME. |
get_workflow(name) | Returns the registered spec or None. |
list_workflows() | Returns a snapshot dict of all registered workflows. |
load_workflows_file(path) | Parses a YAML file with a top-level workflows: list (each step has agent, optional input_map and condition), registers each workflow, and returns the count loaded. Raises FileNotFoundError or ValueError on bad input. |
Routing and QoS
The router learns per-model cost, latency, and quality through exponential moving averages and picks the best candidate per call. QoS policies act as a pre-filter: models that violate the SLA are removed before the selection strategy runs. See Routing and QoS for the full mental model.
CostAwareRouter(weights=None, strategy="thompson", ema_alpha=0.3) supports three
strategies: "score" (deterministic weighted score, lower wins), "thompson"
(the default — Beta Thompson Sampling on success/failure), and "thompson_multi"
(Gaussian Thompson Sampling on a cost/latency/quality utility). Key methods:
register_model(), select_model(candidates),
select_model_explain(candidates) (returns a RoutingDecision with
selected_model, strategy, and per-candidate scores),
record_outcome(model, latency_ms=..., cost_usd=..., success=True, quality=1.0)
(call this after every invocation so the router learns), stats(),
leaderboard(), and dump_state()/load_state() for persistence via
RouterStateManager.
| Dataclass | Fields and defaults |
|---|---|
RoutingWeights |
cost=0.4, latency=0.3, quality=0.3 — each must be in [0, 1]; the router normalises internally. |
ModelStats |
alpha=0.3 (EMA factor), ema_latency_ms=5000.0, ema_cost_usd=0.01, ema_quality=0.8, invocation_count, success_count, ts_alpha=1.0/ts_beta=1.0 (uniform Beta prior), plus the derived success_rate property. |
RoutingDecision |
selected_model, strategy, scores — for "score" lower is better; for "thompson" higher is better. |
QoSLevel defines three tiers and QoSPolicy.for_level(level) returns the
default SLA caps for each. A policy's filter_candidates() never returns an empty
set — if every model fails the SLA, the full candidate list is used (graceful
degradation).
| Tier | Default policy from for_level() |
|---|---|
QoSLevel.FAST | latency < 2,000 ms, quality ≥ 0.5 |
QoSLevel.BALANCED | latency < 5,000 ms, cost < $0.05, quality ≥ 0.7 |
QoSLevel.QUALITY | quality ≥ 0.9, cost < $0.10 |
QoSPolicy fields: max_latency_ms, max_cost_usd, min_quality,
min_success_rate (all optional; None means unconstrained) and level
(default BALANCED). UCB1Router(exploration_c=1.0, weights=None) is a
deterministic bandit that tries unvisited models first and adds
select_model_with_policy(candidates, policy=...).
AdaptiveRouter(explore_threshold=20, exploration_c=1.0, weights=None) uses UCB1
for the first 20 total invocations, then switches to Thompson Sampling; its
active_strategy property reports which phase is live.
Resilience
Every Replicate call inside AgentExecutor runs behind a per-model circuit
breaker with retry and jittered back-off. These classes live in
replicate_mcp.resilience (only is_retryable_error is re-exported at the top
level). Full tuning guidance is in
Configure resilience and caching.
CircuitBreakerConfig field | Default | Description |
|---|---|---|
failure_threshold | 5 | Consecutive failures before the circuit opens. |
recovery_timeout | 60.0 | Seconds in OPEN before transitioning to HALF-OPEN. |
half_open_max_calls | 3 | Maximum concurrent probe calls in HALF-OPEN. |
success_threshold | 2 | Consecutive HALF-OPEN successes needed to close. |
CircuitState has three values: CLOSED (calls flow), OPEN (calls raise
CircuitOpenError immediately), and HALF_OPEN (limited probes allowed).
RetryConfig defaults: max_retries=3, base_delay=0.5,
max_delay=30.0, jitter_factor=0.25, and a retryable_exceptions tuple of
(Exception,). Note that AgentExecutor builds its own RetryConfig from its
max_retries=2 and retry_base=0.5 arguments, so the executor retries twice by
default even though the standalone config defaults to three.
is_retryable_error(exc, config=None) classifies errors in strict order:
NonRetryableError subclasses are never retried, RetryableError subclasses are
always retried, and anything else falls through to the configured tuple.
TokenBucket(rate, capacity) (from replicate_mcp.ratelimit) is the async rate
limiter accepted by AgentExecutor: await acquire(tokens=1.0) blocks until
capacity is available, try_acquire() is the non-blocking variant, and
available_tokens reports the current level.
Cache and discovery
ResultCache is an in-memory, content-addressed cache keyed on a SHA-256 hash of
(model, sorted-JSON payload). It is opt-in: pass it to AgentExecutor(cache=...)
and identical requests within the TTL replay their chunk lists instantly. Constructor
defaults: ttl_s=300.0, max_entries=500, policy=EvictionPolicy.LRU,
background_eviction=False, background_interval_s=60.0. EvictionPolicy
values: LRU (default), TTL (only evicts expired entries), FIFO, and
LFU (reserved; currently falls back to FIFO). Introspection properties include
size, hits, misses, hit_rate, evictions, and a combined
stats dict.
ModelDiscovery(registry=..., config=...) pulls models from the Replicate catalog
and merges them into a registry with register_or_update, so manual customisations
survive refreshes. discover_and_register(...) is the one-shot wrapper, and
start_background_refresh() runs the refresh loop on an interval.
DiscoveryConfig field | Default | Description |
|---|---|---|
owner | None | Restrict discovery to one Replicate owner (e.g. "meta"). |
required_tags | [] | Include a model only if it carries at least one of these tags; empty includes all. |
max_models | 50 | Hard cap per refresh cycle. |
ttl_seconds | 300.0 | Minimum seconds between API calls; earlier refreshes are skipped. |
auto_streaming | True | Register discovered models with streaming enabled. |
background_interval_seconds | 0.0 | Background refresh interval; 0 disables the loop. |
version_pinning | LATEST | VersionPinningMode: LATEST follows the API, EXACT never updates pinned models, MINOR is reserved. |
pinned_versions | {} | Map of "owner/name" to a pinned version hash. |
Distributed execution
The distributed layer dispatches agent calls across worker nodes — in-process queues
for a single machine, or HTTP workers across machines. DistributedExecutor(nodes=None,
max_retries=2) is the coordinator: it is an async context manager, routes each task to
the least-loaded healthy node (skipping remote nodes whose circuit breaker is OPEN), and
fails over up to max_retries times. submit(agent_name, payload) returns an
awaitable TaskHandle that resolves to a TaskResult (task_id,
agent_name, node_id, chunks, status, error,
elapsed_ms; status is one of PENDING, RUNNING, DONE,
FAILED).
| Class | Constructor and role |
|---|---|
WorkerNode | WorkerNode(node_id=None, max_queue_depth=100, concurrency=4) — in-process asyncio worker with a bounded queue; raises NodeOverloadError at capacity. |
WorkerTransport | Abstract transport interface for talking to remote workers. |
HttpWorkerTransport | HttpWorkerTransport(base_url, timeout=120.0) — HTTP implementation hitting POST /execute, GET /health, GET /metrics. |
RemoteWorkerNode | RemoteWorkerNode(node_id, transport=..., concurrency=8) — delegates execution over a transport and caches the worker's circuit state for routing. |
WorkerHttpApp | WorkerHttpApp(executor=None, node_id=None, circuit_config=None) — the Starlette ASGI app a worker serves; returns 503 while its circuit is OPEN. |
WorkerCircuitBreaker / WorkerCircuitState | Worker-side failure tracking exposed through /health so coordinators can fail over; WorkerCircuitOpenError is raised when routing hits an open worker. |
serve_worker launches a worker with uvicorn (requires the [http] extra) and
is what replicate-agent workers start calls under the hood:
async def serve_worker(
*,
host: str = "0.0.0.0",
port: int = 7999,
api_token: str | None = None, # falls back to REPLICATE_API_TOKEN
node_id: str | None = None,
log_level: str = "info",
max_concurrency: int = 8,
enable_circuit_breaker: bool = True,
circuit_config: CircuitBreakerConfig | None = None,
) -> None
Plugins and integrations
Plugins are middleware around every agent invocation. Subclass BasePlugin,
implement the abstract metadata property plus setup() and teardown(),
and override any of three hooks: on_agent_run(agent_name, payload) (return a dict
to replace the payload, or None to pass through), on_agent_result(agent_name,
chunks, latency_ms) (return a list to replace the output chunks), and
on_error(agent_name, error) (observational only — the exception always
propagates). Hooks must not raise. PluginMetadata fields: name,
version (default "0.0.1"), description, author,
requires.
PluginRegistry manages lifecycle and dispatch: load(), load_many(),
unload(name), unload_all(), get(), has(), names(),
count, and the executor-facing dispatch_run() / dispatch_result() /
dispatch_error(). load_plugins(extra_classes=None, skip_names=None) discovers
plugins from the replicate_mcp.plugins entry-point group. Three guardrail plugins
ship built in: PIIMaskPlugin (redacts SSNs, emails, phone numbers, and
card-like sequences), ContentFilterPlugin(deny_list=None), and
CostCapPlugin(per_invocation_cap=1.0, session_cap=10.0).
The Latitude integration (install pip install "replicate-mcp-agents[latitude]")
exports LatitudeClient, LatitudeConfig, LatitudePrompt,
LatitudeTrace, LatitudeEvalResult, LatitudePaymentRequiredError, and
LatitudePlugin. The module-level boolean HAS_LATITUDE is True when the
optional import succeeded — check it before touching the Latitude symbols.
Configuration falls back to the LATITUDE_API_KEY and LATITUDE_PROJECT_SLUG
environment variables.
Exceptions
Every framework error derives from ReplicateMCPError, so one
except ReplicateMCPError clause catches anything the library raises. The
classification pair RetryableError / NonRetryableError drives
is_retryable_error. The hierarchy (modules other than
replicate_mcp.exceptions noted in parentheses):
ReplicateMCPError
├── CycleDetectedError
├── NodeNotFoundError
├── WorkflowValidationError
├── ModelNotFoundError
├── ExecutionError
│ └── ExecutionTimeoutError
├── TokenNotSetError
├── DuplicateAgentError
├── AgentNotFoundError
├── TransformNotFoundError
├── ConditionNotFoundError
├── CheckpointCorruptedError
├── RetryableError
│ ├── RateLimitError
│ └── ServerError
├── NonRetryableError
│ ├── AuthenticationError
│ └── ClientError
├── CircuitOpenError (resilience)
├── MaxRetriesExceededError (resilience)
├── NodeOverloadError (distributed)
├── NoHealthyNodesError (distributed)
└── WorkerCircuitOpenError (distributed)
| Exception | Raised when |
|---|---|
CycleDetectedError | A workflow DAG contains a cycle; carries the offending node path. |
NodeNotFoundError | A workflow references a node that does not exist. |
WorkflowValidationError | A workflow fails structural validation. |
ModelNotFoundError | An agent or model ID cannot be resolved; lists available IDs. |
ExecutionError / ExecutionTimeoutError | A Replicate invocation fails, or exceeds its deadline. |
TokenNotSetError | REPLICATE_API_TOKEN is missing from the environment. |
DuplicateAgentError / AgentNotFoundError | Registering an existing safe_name, or looking up an unregistered one. |
TransformNotFoundError / ConditionNotFoundError | A named transform or condition is missing from its registry. |
CheckpointCorruptedError | A checkpoint file cannot be deserialised. |
RateLimitError / ServerError | Retryable: a 429 (with optional retry_after) or a 5xx from upstream. |
AuthenticationError / ClientError | Non-retryable: invalid token, or a 4xx bad request. |
CircuitOpenError / MaxRetriesExceededError | A call is rejected by an OPEN breaker, or all retry attempts are exhausted. |
NodeOverloadError / NoHealthyNodesError / WorkerCircuitOpenError | A worker queue is full, no healthy worker exists, or a worker's breaker is OPEN. |
Next steps
- CLI reference — the commands that drive these classes from the shell.
- Architecture — how the subsystems on this page fit together.
- Agents & workflows — task-oriented usage of the SDK surface.