v0.34 on PyPI · open source · connect agents to any API

Connect your agent to
any API — on the fly

Liquid discovers any HTTP API, maps it to the shape you ask for, and serves typed data to your agent. AI runs once at setup — every sync after is deterministic and costs no model tokens. Token-aware search, cross-API normalization, and self-healing come built in.

Connect any API on the fly AI only at setup — fixed cost Cross-API normalization Structured self-healing Open source (AGPL-3.0)
−98%
Tokens on search
1,519 vs 75,482
Cross-API consistency
0.11 → 1.00 field overlap
2,500+
Pre-discovered APIs
Zero setup cost
Structured
Self-recovery
next_action on every error

Measured on realistic agent tasks against deterministic fixtures. See full benchmarks →

How it works

Discover once. Sync forever.

AI discovers and maps an API once (or reuses the catalog). Everything after is a deterministic runtime — every layer optimizes for the agent.

1

Discover

Pull from the 2,500+ API catalog, or discover on the fly: OpenAPI → GraphQL → REST heuristic → browser. Cheapest method first.

2

Map

AI maps fields to the shape you asked for, once. Normalize shapes (Money, DateTime, pagination), compile intent verbs, build token estimators — all saved into a deterministic adapter.

3

Serve

Expose as framework-native tools. Every call runs the token-aware runtime — search, aggregate, estimate, budget, truncate — no model in the loop.

4

Recover

Errors carry structured next_action. Schema drift triggers auto-repair. Rate limits surface as retry_after. The agent never reads stack traces.

What Liquid does for your agent

Six things every agent needs
that raw HTTP doesn't give you

Token budgets. Cross-API cognitive load. Canonical intents. Error recovery. Cost prediction. Ambient state. All at the transformation layer — not in your prompt.

Token economy

Server-side search & aggregate

Filter, project, aggregate, text-search — all before bytes reach the context window. Budget caps and fetch_until predicates end the “fetch everything, filter in prompt” anti-pattern.

# −98% tokens vs blind fetch
await liquid.search(
  adapter, "/orders",
  where={"total_cents": {"$gt": 10000}},
  limit=20,
)
Normalization

One mental model per domain

Stripe, PayPal, Square, Adyen all collapse into one Money(amount_cents, currency). Dates become UTC datetime. Pagination envelopes flatten. Your agent writes one parser, not four.

# normalize on the client; connect by URL
liquid = Liquid(..., normalize_output=True)
adapter = await liquid.get_or_create(
  "https://api.stripe.com",
  target_model={"amount_cents": "int"},
)
# → Money(amount_cents=9999, currency="USD")
Intent layer

Call charge_customer() anywhere

Intent-level verbs like charge_customer, create_ticket, post_message work across vendors. Swap Stripe for PayPal with one config change — the agent's tool call doesn't change.

await liquid.execute_intent(
  "charge_customer",
  {"customer_id": "cus_42",
   "amount_cents": 9999,
   "currency": "USD"}
)
Self-healing

Every error carries a next_action

401 → store_credentials. 404 → repair_adapter. 429 → retry_after_seconds. Agents dispatch the suggested tool without parsing error text. No human in the loop for known failure modes.

try:
  await liquid.fetch(adapter)
except AuthError as e:
  # structured, not a string
  agent.call(e.recovery.next_action)
Predictable cost

Estimate before you spend

estimate_fetch() returns items, bytes, tokens, credits, latency — with zero HTTP calls. Tool metadata (cost_credits, cached, idempotent, side_effects) lets the agent plan routes, not hope for the best.

est = await liquid.estimate_fetch(
  adapter, "orders",
)
if est.expected_tokens > budget:
  # switch to aggregate / search
Ambient state

Ask instead of remembering

to_tools() auto-attaches liquid_check_quota, liquid_check_rate_limit, liquid_health_check, liquid_estimate_fetch, liquid_search_nl, and more. The agent discovers state rather than carrying it in context.

tools = adapter.to_tools(
  format="anthropic",
)
# includes ambient introspection
# tools alongside adapter tools
Measured impact

Every claim is reproducible

Run python -m benchmarks.run against the fixtures — fresh numbers, same delta, every time. No cherry-picked marketing graphs.

Task Baseline With Liquid Delta
Find 10 orders over $100 75,482 tok 1,519 tok −98%
Revenue by status (aggregate) 75,482 tok 115 tok −100%
Fetch customer id + email only 424 tok 12 tok −97%
Find the shipping ticket (text search) 14,588 tok 154 tok −99%
Stripe ↔ PayPal field consistency 0.11 overlap 1.00 overlap
Skip wasted call via estimate 14,943 tok 0 tok −100%
max_tokens=2000 budget cap 14,943 tok 1,999 tok −87%
Recover from 401 no next_action structured

Methodology, fixtures, and raw JSON in benchmarks/RESULTS.md.

Framework-native

One call. Every agent framework.

to_tools() emits the shape your framework expects — with ambient introspection tools included.

Anthropic
"anthropic"
OpenAI
"openai"
LangChain
"langchain"
MCP
"mcp"
CrewAI
liquid-crewai
# One call, any framework tools = adapter.to_tools(format="anthropic") # or "openai", "langchain", "mcp" # CrewAI goes through the dedicated toolkit: from liquid_crewai import LiquidCrewToolkit tools = LiquidCrewToolkit(adapter, liquid).get_tools() # Includes adapter tools + ambient state tools: # liquid_check_quota, liquid_check_rate_limit, liquid_health_check, # liquid_estimate_fetch, liquid_aggregate, liquid_text_search, # liquid_search_nl, liquid_fetch_until, liquid_fetch_changes_since, # liquid_list_adapters
In practice

A complete agent loop

Normalized output, token-aware search, structured recovery — in one example.

# pip install liquid-api
from liquid import Liquid
from liquid._defaults import InMemoryVault, InMemoryAdapterRegistry, CollectorSink

liquid = Liquid(
    llm=my_llm, vault=InMemoryVault(), sink=CollectorSink(),
    registry=InMemoryAdapterRegistry(), normalize_output=True,
)

# 1. Discover + map any API once — connect by URL, no pre-built integration
adapter = await liquid.get_or_create(
    "https://api.stripe.com",
    target_model={"id": "str", "amount_cents": "int", "currency": "str"},
)

# 2. Budgeted, server-side search — not "fetch everything, filter in prompt"
try:
    charges = await liquid.search(
        adapter, "/charges",
        where={"amount_cents": {"$gt": 10_000}},
        fields=["id", "amount_cents", "currency"],
        limit=20,
    )
except LiquidError as e:
    # 3. Structured recovery — dispatch the suggested tool, no text parsing
    agent.call(e.recovery.next_action)   # → store_credentials(...)

# 4. Hand the whole kit to the agent, one call
tools = adapter.to_tools(format="anthropic")
Install

Two minutes to your first tool call

~/your-agent
$ pip install liquid-api
Successfully installed liquid-api-0.34.0
# point Liquid at any API, get typed records back:
>>> adapter = await liquid.get_or_create(url, target_model={...})
>>> await liquid.fetch(adapter) # deterministic, 0 LLM calls
How we compare

Liquid vs the alternatives

The real question isn't HTTP access — it's connecting to APIs you never pre-integrated, and shaping them for the agent's budget.

Capability Liquid MCP server Composio DIY
Connect to any API on the fly (no pre-build) ~
Pre-mapped API catalog ~
Managed auth / OAuth handled for you ~ ~
Token-aware search / aggregate (server-side)
Cross-API output normalization ~
Structured recovery (next_action)
Deterministic, reproducible runtime ~ ~
Self-healing on schema drift
Open source ~ n/a

Liquid auto-discovers any API on the fly — its 2,500+ pre-mapped catalog and Composio's 500+ managed-auth integrations are complementary, not the same axis. Per-API MCP servers cover one API each. On managed auth, Liquid already auto-refreshes OAuth2 tokens and stores credentials encrypted per-tenant — you register the OAuth app once (bring your own client_id/secret); hosted "Connect with…" consent flows are on the roadmap. Competitor data: composio.dev, May 2026.

Ecosystem

Three ways to connect

Use the transport that fits your agent. Same transformation layer, same adapters, same catalog.

PRIMARY

Python SDK

pip install liquid-api. Async-first, type-hinted, framework-native via to_tools().

from liquid import Liquid
adapter = await liquid.get_or_create(url, target_model=...)
tools = adapter.to_tools("anthropic")
CLAUDE / IDE

MCP Server

Model Context Protocol, stdio transport. Point it at the hosted API; your agent connects to any API by URL.

liquid_connect
liquid_fetch
liquid_query
REST

HTTP API

Language-agnostic. Same transformation layer, swagger docs at /docs.

POST /v1/connect
POST /v1/fetch
POST /v1/query
Built to be trusted

Verify, don't trust

No logos to wave yet — instead, everything you'd want to check is open and reproducible.

🔐 Credentials encrypted per-tenant (AES-256-GCM)
🛡️ SSRF-guarded — no reach to internal/metadata addresses
⏱️ Per-API-key rate limits
🎯 No per-call LLM — predictable cost, reproducible runs
📖 Open source (AGPL-3.0) — audit every line
🔓 No lock-in — self-host the whole engine

Don't take our word for it — read the code and reproduce the benchmarks yourself.
Report a security issue · see what we ship · talk to the founder

Stop writing an integration per API.

Point Liquid at any API and ship. Start free, or lock in lifetime founder access.