Observed since 20 Oct, 23:19 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
AgentSeek API core runtime with OceanBase checkpoints.
English | 中文
[!WARNING] This project is under active development and is not production-ready. Pull requests for bug fixes and enhancements are warmly welcomed!
Run LangGraph and LangChain apps behind a FastAPI runtime with a standalone
agentseek-api CLI.
[!NOTE] AgentSeek API uses Agent Protocol as the main external compatibility reference. The current runtime covers the core thread, run, cron, streaming (including subgraph and expanded stream modes), and protocol-v2 event flows. Auth uses the
langgraph_sdk.Authpattern with@auth.authenticateand@auth.onhandlers. Agent resources are exposed through/assistants, direct/agentsaliases, Streamable HTTP MCP, and LangSmith-style A2A endpoints. This is workable OSS parity for the core agent-server surfaces, not full LangSmith Agent Server parity.
Current release boundary:
uv| Workflow | Use it when | Recommended command |
|---|---|---|
langgraph dev | You want the fastest mocked or in-memory local API loop for graph prototyping or Studio experimentation. | langgraph dev |
agentseek-api dev | You want the real AgentSeek API surface with your actual MySQL-family / seekdb / OceanBase-style persistence, auth, and Docker/runtime behavior. | uv run agentseek-api dev |
Use langgraph dev when you do not need real backend validation. Use
agentseek-api dev when you want to exercise the actual API contract this repo
ships.
Install as a project dependency (recommended):
# In your project directory
uv add agentseek-api
# With embedded seekdb backend (no Docker needed)
uv add agentseek-api[embedded]
Global install (if you prefer a system-wide command):
pip install agentseek-api
# Then install your graph's dependencies into the same environment
pip install ...
[!WARNING] Global install only supports
pip install. Do NOT useuv tool install.
Install from source (for contributors):
uv sync
# With embedded seekdb backend
uv sync --extra embedded
The fastest way to get a real backend running locally is seekdb embed — an in-process seekdb instance, no Docker or separate process required:
SEEKDB_EMBED=true agentseek-api dev
Data is stored in ~/.agentseek/seekdb_data by default. Set SEEKDB_EMBED_DIR
to change the location.
docker run -d --name seekdb-dev \
-p 2881:2881 -p 2886:2886 \
oceanbase/seekdb:latest
Wait for the container to become healthy, then export:
export OCEANBASE_HOST=127.0.0.1
export OCEANBASE_PORT=2881
export OCEANBASE_USER=root
export OCEANBASE_PASSWORD=
export OCEANBASE_DB_NAME=seekdb
Start an OceanBase-CE container in mini mode:
docker run -d --name ob-dev \
-e MODE=mini \
-p 2881:2881 \
oceanbase/oceanbase-ce:latest
OceanBase-CE in mini mode takes a few minutes to initialize. Wait for readiness, then export:
export OCEANBASE_HOST=127.0.0.1
export OCEANBASE_PORT=2881
export OCEANBASE_USER=root@test
export OCEANBASE_PASSWORD=
export OCEANBASE_DB_NAME=seekdb
Create the database:
mysql -h 127.0.0.1 -P 2881 -u root@test -e "CREATE DATABASE IF NOT EXISTS seekdb"
agentseek-api looks for config in this order:
AGENTSEEK_GRAPHS, if it points to an existing fileagentseek.jsonlanggraph.jsonMinimal langgraph.json:
{
"$schema": "https://langgra.ph/schema.json",
"dependencies": ["."],
"graphs": {
"chat": "chat.graph:graph"
}
}
uv run agentseek-api dev
Run with an explicit config when needed:
uv run agentseek-api dev --config ./langgraph.json
When the server starts it prints the banner and local URLs:
Welcome to
╔═╗┌─┐┌─┐┌┐┌┌┬┐╔═╗┌─┐┌─┐┬┌─
╠═╣│ ┬├┤ │││ │ ╚═╗├┤ ├┤ ├┴┐
╩ ╩└─┘└─┘┘└┘ ┴ ╚═╝└─┘└─┘┴ ┴
AgentSeek v0.2.3
- 🚀 API: http://localhost:2024
- 📚 Docs: http://localhost:2024/docs
- 🎨 Studio UI: https://smith.langchain.com/studio/?baseUrl=http://127.0.0.1:2024
curl http://127.0.0.1:2024/health
curl http://127.0.0.1:2024/info
curl http://127.0.0.1:2024/openapi.json
from langgraph_sdk import get_client
client = get_client(url="http://localhost:2024/")
async def main():
# List all assistants
assistants = await client.assistants.search(graph_id="agent")
# We auto-create an assistant for each graph you register in config.
agent = assistants[0]
# Start a new thread
thread = await client.threads.create()
# Start a streaming run
input = {"messages": [{"role": "human", "content": "hello?"}]}
async for chunk in client.runs.stream(
thread["thread_id"], agent["assistant_id"], input=input
):
print(chunk)
if __name__ == "__main__":
import asyncio
asyncio.run(main())
The package installs agentseek-api as the standalone executable. It does not
install a top-level agentseek binary, which keeps the namespace free for a
parent CLI.
agentseek-api <command> [arguments]
When running from this repository, use uv run agentseek-api ....
| Command | What it does |
|---|---|
dev | Start the API with reload for local development. |
serve | Start the API without reload for containers or smoke tests. |
worker | Start the Redis-backed run worker. |
dockerfile | Generate a runtime Dockerfile for the active config. |
build | Build a Docker image for the active config. |
up | Start a local Docker runtime for the active config. |
version | Print the installed package version. |
-c, --config PATH: explicit agentseek.json, langgraph.json, or manifest
path--env-file PATH: host-runtime dotenv sourceFor dev, serve, worker, and scheduler, direct assignments are applied in
this order:
env;env mapping and auth.path;--env-file;agentseek-api.The inherited environment is authoritative by key presence. This includes an
explicit empty value. A lower source can fill an absent key, but cannot replace
an inherited KEY=.
Each dotenv file is evaluated independently. It can reference the inherited environment and earlier bindings in the same physical file; it cannot reference a config mapping or another dotenv file. Later assignment does not recompute an earlier interpolated value.
In dotenv syntax, a bare KEY is valid but contributes no assignment, while
KEY= contributes an explicit empty string. Missing files, invalid UTF-8, and
malformed syntax stop the command before a runtime child starts.
The CLI applies command-owned values after this merge: the selected config path
becomes AGENTSEEK_GRAPHS, and dev forces STUDIO_AUTH_LOCAL_DEV=true.
Host and port options are passed as child argv and do not rewrite environment
keys with similar names.
uv run agentseek-api dev
uv run agentseek-api serve --config ./langgraph.json --port 8080
uv run agentseek-api worker --config ./langgraph.json
uv run agentseek-api dockerfile --config ./langgraph.json ./agentseek-build-bundle
uv run agentseek-api build --config ./langgraph.json -t agentseek-api:dev
uv run agentseek-api up --config ./langgraph.json --port 8123 --wait
uv run agentseek-api version
dev
127.0.0.12024--no-reload to disable reload--no-browser to suppress automatic Studio launch--studio-url to point at a different LangSmith / Studio originserve
devworker
EXECUTOR_BACKEND=redisREDIS_URL plus the queue keys belowscheduler
build
-t, --tag to set the image tag--platform, --pull, and --no-pulldockerfile
Dockerfile, sanitized runtime manifest, and selected project files; the
output argument is a new directory, not a standalone Dockerfile pathup
--wait, --image, --base-image, --postgres-uri,
--recreate, and --no-recreate--pass-env NAME explicitly selects a resolved application value for the
direct Docker carrier; the value is inherited by name and never put in argv--compose-pass-env NAME explicitly selects a resolved application value
for Compose interpolation; config can make the same selection with
compose_envSome LangGraph CLI-shaped flags are parsed for command compatibility but
rejected when their runtime behavior is not implemented yet. For mocked,
in-memory, or tunneled local workflows, prefer langgraph dev.
agentseek.json, langgraph.json,
or AGENTSEEK_GRAPHS/assistants and /agentsPOST /threads/{thread_id}/runs/{run_id}/resumelangchain-oceanbaselanggraph_sdk.Auth-based authentication with @auth.authenticate and
@auth.on handlers; noop fallback when unconfiguredTreat AgentSeek API as a practical OSS-compatible core for Agent Server-style apps.
Cron-enabled deployments run three long-lived roles:
/assistants, /threads, /runs, /runs/crons, /info, and the other HTTP surfacesFor local development against a real backend, use uv run agentseek-api dev.
For mocked or in-memory graph iteration, use langgraph dev instead. For
durable cron execution, run the API server, worker, and scheduler together
against the same database and Redis instance.
Graph references may point to:
package.module:graph./graph.py:graphbuild_graph(checkpointer=...) functionUseful config fields:
dependencies: local package paths installed into generated Docker imagesgraphs: graph id to graph reference mappingenv: either a dotenv file path or an object of scalar environment valuesauth.path: custom auth backend referenceauth.openapi: OpenAPI securitySchemes and security metadata for authauth.disable_studio_auth: disables the Studio auth bypass described belowhttp.disable_mcp: disable the MCP endpointhttp.disable_a2a: disable the A2A endpoint and agent-card discovery routebase_image, python_version, image_distro, pip_config_file,
dockerfile_lines: Docker build customization fieldsbuild_include: additional trusted regular files or directory trees to copy
into the sanitized build bundlecompose_env: names from the already-resolved application environment that
may cross into an explicitly selected Compose dotenv carrierThe preloaded-v1 contract is a breaking, fail-closed container boundary. The
host resolves application configuration once. Containers started from generated images receive only
the selected runtime payload, while ambient host values, dotenv files, package
credentials, and unselected Compose values stay outside the build context and
image layers. Use --pass-env or --compose-pass-env only for trusted input;
these flags authorize a value to cross the named runtime boundary, not to enter
the build.
build_include is also a trusted-input declaration: review every selected path.
Credentialed Python indexes belong in pip_config_file, which is mounted as a
BuildKit pip secret and is not copied into the context. The dockerfile command
now writes the complete bundle directory consumed by Docker rather than a lone
Dockerfile.
Custom images must expose all four exact labels:
org.agentseek.environment-contract=preloaded-v1org.agentseek.runtime-manifest=/opt/agentseek/manifest.v1.jsonorg.agentseek.runtime-distribution=agentseek-apiorg.agentseek.runtime-version=0.3.3The manifest, installed distribution, entrypoint, and labels must agree. There
is no legacy-image fallback: migrate and attest the image before passing it to
up --image, or keep using the older launcher with the older image. Release
Train A coordinates are API 0.2.3, templates 0.1.3, and AgentSeek 0.1.3; the
The planned Train B template/catalog release is 0.1.4. The separate planned
AgentSeek release is also 0.1.4; both follow the shipped 0.1.3 releases.
Endpoint-level LangGraph config keys such as http and api_version are
tolerated by the CLI layer where possible. Store config is used by the HTTP
Store API and the injected LangGraph BaseStore runtime for TTL and semantic
search. This repo uses the published langchain-oceanbase>=0.6.4,<0.7 package from
PyPI.
Config-driven custom auth can live in agentseek.json or langgraph.json:
{
"$schema": "https://langgra.ph/schema.json",
"dependencies": ["."],
"graphs": {
"chat": "chat.graph:graph"
},
"auth": {
"path": "./auth.py:auth",
"openapi": {
"securitySchemes": {
"apiKeyAuth": {
"type": "apiKey",
"in": "header",
"name": "X-API-Key"
}
},
"security": [{ "apiKeyAuth": [] }]
},
"disable_studio_auth": false
}
}
/docs, /redoc, and /openapi.jsonagentseek-api devagentseek-api dev accepts loopback Studio requests
carrying x-auth-scheme: langsmithauth.disable_studio_auth to true if Studio should use the same normal
API auth path as every other client during devlanggraph dev instead of AgentSeekAgentSeek API exposes registered graphs as MCP tools through a stateless
Streamable HTTP endpoint at /mcp.
/mcp and /mcp/ are both acceptedagentseek.json,
langgraph.json, or AGENTSEEK_GRAPHShttp.disable_mcp: true disables itGraph object entries can carry MCP-facing metadata directly in the manifest:
{
"graphs": {
"docs_agent": {
"graph": "./docs_agent.py:graph",
"name": "docs_agent",
"description": "Answers documentation questions",
"input_schema": {
"type": "object",
"properties": {
"question": { "type": "string" }
},
"required": ["question"]
},
"output_schema": {
"type": "object",
"properties": {
"answer": { "type": "string" }
},
"required": ["answer"]
}
}
}
}
When these fields are omitted, AgentSeek falls back to:
{"type": "object"}{"type": "object"}Set http.disable_mcp in your config file:
{
"$schema": "https://langgra.ph/schema.json",
"graphs": {
"chat": "chat.graph:graph"
},
"http": {
"disable_mcp": true
}
}
import httpx
from mcp import ClientSession
from mcp.client.streamable_http import streamable_http_client
async with httpx.AsyncClient(
headers={"X-API-Key": "secret"},
trust_env=False,
) as http_client:
async with streamable_http_client(
url="http://127.0.0.1:2024/mcp",
http_client=http_client,
) as (read, write, _):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
print(tools)
This milestone only covers exposing AgentSeek graphs as MCP tools. It does not add outbound MCP client support inside AgentSeek graphs.
AgentSeek API exposes assistants through a LangSmith-style A2A endpoint at
/a2a/{assistant_id} plus agent-card discovery at
/.well-known/agent-card.json?assistant_id={assistant_id}.
message/send, message/stream, tasks/get, tasks/cancel/.well-known/agent-card.json/a2a/{assistant_id} onlycontextId is forwarded as LangGraph thread_idhttp.disable_a2a: true disables both the RPC endpoint and agent-card discoverySet http.disable_a2a in your config file:
{
"$schema": "https://langgra.ph/schema.json",
"graphs": {
"chat": "chat.graph:graph"
},
"http": {
"disable_a2a": true
}
}
import httpx
assistant_id = "<assistant-id>"
payload = {
"jsonrpc": "2.0",
"id": "send-1",
"method": "message/send",
"params": {
"message": {
"role": "user",
"parts": [{"kind": "text", "text": "hello"}],
"messageId": "msg-1",
}
},
}
with httpx.Client(headers={"X-API-Key": "secret"}, trust_env=False) as client:
response = client.post(
f"http://127.0.0.1:2024/a2a/{assistant_id}",
json=payload,
headers={"Accept": "application/json"},
)
response.raise_for_status()
print(response.json())
This endpoint targets practical LangSmith parity for assistant-to-assistant messaging and SDK interoperability. Task tracking is in-process, so task lookup and cancellation only apply to tasks created on the current API process.
Embed the FastAPI app directly:
from agentseek_api.main import create_app
app = create_app()
Mount the CLI under a parent tool without giving up the standalone
agentseek-api binary:
import argparse
from agentseek_api.cli import register_subcommands, run_namespace
parser = argparse.ArgumentParser(prog="parent")
subparsers = parser.add_subparsers(dest="tool", required=True)
register_subcommands(subparsers, command_name="api")
args = parser.parse_args()
raise SystemExit(run_namespace(args))
That lets a parent CLI expose commands like:
parent api dev --config ./langgraph.json
parent api build --config ./langgraph.json -t my-api:dev
METADATA_DB_URL when it is setSEEKDB_URL or the
OCEANBASE_* connection settingsEXECUTOR_BACKEND=inlineEXECUTOR_BACKEND=redis and start agentseek-api worker to hand off
runs through RedisREDIS_URL=redis://127.0.0.1:6379/0REDIS_RUN_QUEUE_KEY=agentseek:runs:pendingREDIS_RUN_PROCESSING_KEY=agentseek:runs:processingWORKER_CONCURRENT_JOBS=10 bounds concurrently executing jobs in one
worker processREDIS_WORKER_LOCK_KEY=agentseek:worker:activeREDIS_WORKER_LOCK_TTL_SECONDS=30REDIS_STREAM_MAXLEN=10000REDIS_STREAM_TTL_SECONDS=3600METADATA_DB_BACKEND=auto normalizes drivers:
postgresql+asyncpg://...mysql+aiomysql://...sqlite+aiosqlite://...METADATA_DB_BACKEND=sqlite, they are stored in the configured SQLite
metadata database without constructing an OceanBase saver.agentseek.json "auth.path" or AUTH_MODULE_PATH env var.
Uses langgraph_sdk.Auth with @auth.authenticate and @auth.on handlers.
If not set, all requests pass through as default_user (noop).@auth.on handlers.scripts/benchmark_stream_persistence.py.
It exercises the real API with temporary SQLite storage or native embedded
seekdb (--backend embedded), checks output/checkpoints/replay, and makes no
model-provider calls. SQL latency injection is optional. Use --repeat for
median/maximum timings; embedded CI also enforces SQL operation budgets.
See the embedded performance report
for measured latency, backend details, and reproduction commands.examples/minimal_agentseek/agentseek.json: minimal first-time configexamples/assistant_config/: assistant config/context/metadata starterexamples/auth/api_key_auth.py: API key authentication using langgraph_sdk.Authexamples/auth/bearer_token_auth.py: bearer token authenticationexamples/auth/jwt_auth.py: JWT authentication with JWKS validationexamples/auth/custom_backend.py: custom auth backendexamples/auth/jwt.md: JWT auth environment contractexamples/custom_routes/app.py: mounting custom FastAPI routes around the
AgentSeek API appThis repository uses a GitFlow-lite workflow:
main: production-ready history onlydevelop: integration branch for ongoing developmentfeature/<topic>: branch from develop, PR back to developrelease/<version>: branch from develop, PR to mainhotfix/<topic>: branch from main, PR to main, then merge back into
developSee CONTRIBUTING.md for the full branching and CI policy.
Useful local checks:
make test
make test-cov
make test-cli
make test-samples
Docker and live backend checks:
make test-cli-docker
make test-e2e
make test-seekdb
make test-redis-docker
GitHub Actions also runs the Docker-backed backend matrix against MySQL,
seekdb, and OceanBase, including the dedicated Redis Durable Execution
workflow jobs.
For local embedded seekdb smoke coverage, install the optional extra first:
uv sync --dev --extra embedded
This repository intentionally uses two GitHub Actions workflows for CI:
.github/workflows/ci.yml
.github/workflows/live-provider-streaming.yml
The design intent is:
ci.yml proves the product logic, storage/runtime integrations, and backend
compatibility without depending on a live model providerlive-provider-streaming.yml proves that the same API surfaces still work
when a real provider is in the loopThe live-provider workflow is the canonical proof for incremental SSE
messages/partial events from provider-backed graphs, and it also covers
provider-backed Store, MCP, and HITL flows in a tiered backend matrix:
Workflow behavior:
Use ci.yml for the normal development signal, and use
live-provider-streaming.yml when you need explicit proof that real providers
still satisfy the intended streaming, Store, MCP, and HITL contracts.
AgentSeek API is glue around a small set of upstream projects and infra.
Core pillars
EXECUTOR_BACKEND=redis/assistants, /threads, /runs, /mcp, /a2a surface/mcp/a2aRuntime & API
agentseek-api dev and serve/scalarLangChain / LangGraph stack
Database drivers
Interop
Packaging & runtime delivery
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.3.3 | 2 Oct 2026 | 23 |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 23:19 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:ed131df383540da73619a7c3eda2c11486600c135345a84aa4d40bb3c30e74f2