10xgraph.json configuration reference
In shortEvery key the 10xgraph.json config file accepts, with defaults, types, purposes, and complete examples for rate limiting, auth, and servers.
- 6 min read
- 8 sections
- Updated
- v0.10.0
- Markdown
10xgraph.json is the configuration file for the 10xGraph API server and CLI. It specifies which graph to serve, how to authenticate, where state lives, and server behavior. Only the agent key is required; every other key is optional. The file is plain JSON. Edit it by hand or with 10xgraph config (a browser editor).
Projects created before 0.7.0 use agentflow.json. It still works until 2.0: the CLI and the server read it when 10xgraph.json is missing from the same directory. The keys are identical, so migration is a rename (mv agentflow.json 10xgraph.json) or a save from 10xgraph config.
Which keys does it accept?
| Key | Type | Default | Purpose |
|---|---|---|---|
agent |
string | required | Compiled graph as module:attribute, for example graph.agent:app |
env |
string | none | Dotenv file to load before the graph starts, for example .env |
auth |
string, object or null | null |
Authentication: "jwt", or {"method": "custom", "path": "module:Class"} |
authorization |
string, object or null | by MODE |
Access control backend |
injectq |
string or null | none | Import path of an InjectQ container |
store |
string or null | none | Import path of a BaseStore for long-term memory |
checkpointer |
string or null | none | Not applied by the API server. Pass the checkpointer to compile() |
thread_name_generator |
string or null | none | Import path of a thread name generator |
redis |
string or null | none | Redis URL for the shared ownership cache. Falls back to REDIS_URL |
remote_tools |
array | [] |
Schemas of tools that run in the client |
rate_limit |
object | absent (off) | Request rate limiting |
websocket |
object | built-in caps | WebSocket connection limits |
ag_ui |
object | disabled | AG-UI protocol endpoint |
observability |
object | absent | Logfire and LangSmith tracing |
test |
object | absent | Defaults for 10xgraph test |
evaluation |
object | absent | Defaults for 10xgraph eval |
Import paths use module:attribute. Unknown top-level keys are kept in the file but ignored.
auth
| Value | Meaning |
|---|---|
null or absent |
No authentication. Every request runs as anonymous, and the server logs a warning |
"jwt" |
Verify bearer JWTs. Needs JWT_SECRET_KEY and JWT_ALGORITHM |
{"method": "custom", "path": "auth.agent_auth:AgentAuth"} |
Load a BaseAuth subclass. Both method and path are required |
See Server authentication for the full guide.
authorization
| Value | Meaning |
|---|---|
"ownership" |
A thread is accessible only to the user who owns it |
"allow_all", "default", "none" |
Any authenticated user may do anything |
"module:attribute" |
Custom AuthorizationBackend |
{"backend": "rbac", ...} |
Role-based scopes plus owner isolation |
| absent | ownership when MODE=production, otherwise allow-all |
RBAC object keys:
| Key | Type | Default | Purpose |
|---|---|---|---|
backend |
string | required | rbac, role_based or roles (type is also accepted) |
roles |
object | {} |
Role name to a list of scopes. "*" grants every scope. role_scopes is also accepted |
default_scopes |
array | [] |
Scopes granted to everyone |
isolation |
string | owner |
owner or none: whether storage is scoped per user |
Scopes are checkpointer:read|write|delete, config:read, files:read|upload, graph:fix|invoke|read|setup|stop|stream and store:read|write|delete.
rate_limit
Rate limiting applies to REST requests. /ping is always excluded. Set "enabled": false to keep the block without enforcing it.
| Key | Type | Default | Purpose |
|---|---|---|---|
enabled |
boolean | true |
Turn limiting on or off |
backend |
string | memory |
memory, redis or custom (bind a BaseRateLimitBackend in InjectQ) |
requests |
integer | 100 |
Requests allowed per window. Must be above 0 |
window |
integer | 60 |
Window length in seconds. Must be above 0 |
by |
string | ip |
Count per ip, user or global |
exclude_paths |
array | [] |
Extra paths to skip |
redis |
object or string | none | {"url": "...", "prefix": "..."} or a URL string. $VAR and ${VAR} are expanded |
redis.prefix |
string | 10xgraph:rate-limit |
Redis key prefix |
fail_open |
boolean | true |
Allow requests when the backend errors. false denies them |
trusted_proxy_headers |
boolean | false |
Honour X-Forwarded-For. Only behind a proxy you control |
trusted_proxy_hops |
integer | 1 |
Proxies you control, counted from the right of X-Forwarded-For. At least 1 |
trusted_proxies |
array | [] |
IPs or CIDR ranges your proxies connect from. Others cannot spoof the header |
The memory backend counts per process, so with N workers the real limit is requests times N and it resets on restart. Use redis for any multi-worker deployment.
websocket, ag_ui and observability
| Key | Type | Default | Purpose |
|---|---|---|---|
websocket.max_connections |
integer or null | 1000 |
Concurrent connections per process. 0 or null means unlimited |
websocket.max_connections_per_user |
integer or null | 10 |
Per verified user. 0 or null means unlimited |
websocket.realtime_models |
array of strings | [] |
Models a /v1/graph/live client may request |
ag_ui.enabled |
boolean | false |
Mounts POST /v1/ag-ui. Needs the ag-ui extra |
ag_ui.allow_client_tools |
boolean | true |
Offer tools sent by the AG-UI client to the model |
observability.level |
string | standard |
spans, standard or full (full may record PII) |
observability.logfire |
object | none | Keys include enabled, service_name, send_to_logfire, console |
observability.langsmith |
object | none | Keys include enabled, project, endpoint |
Tokens stay in the environment: LOGFIRE_TOKEN and LANGSMITH_API_KEY are never read from the file.
remote_tools
Each entry declares a tool the model can call that runs in the client. Unknown fields are rejected and tool names must be unique.
| Key | Type | Required | Purpose |
|---|---|---|---|
node |
string | yes | Graph node the tool belongs to |
name |
string | yes | Tool name |
description |
string | yes | Description shown to the model |
parameters |
object | no | JSON Schema with type: "object". Defaults to no properties |
test and evaluation
| Key | Type | Default | Purpose |
|---|---|---|---|
test.path |
string | pytest discovery | Test directory or file |
test.coverage |
boolean | false |
Run with coverage |
test.coverage_threshold |
integer | none | Fail below this percentage |
evaluation.directory |
string | evals |
Where eval files live |
evaluation.output_dir |
string | eval_reports |
Report directory |
evaluation.threshold |
number | none | Minimum pass rate, 0 to 1 |
evaluation.parallel |
boolean | false |
Run cases concurrently |
evaluation.max_concurrency |
integer | 4 |
Concurrent cases when parallel |
Environment variables
The server reads configuration from environment variables, which are listed in full in the environment variables reference. Common ones include MODE, IS_DEBUG, JWT_SECRET_KEY, JWT_ALGORITHM, ORIGINS, MAX_REQUEST_SIZE, REDIS_URL, SENTRY_DSN, and OTEL/observability settings. Set them as process environment variables or in a .env file referenced by the env key in 10xgraph.json.
What does a complete config look like?
{
"agent": "graph.agent:app",
"env": ".env",
"auth": "jwt",
"authorization": "ownership",
"injectq": "graph.agent:container",
"store": null,
"redis": "redis://localhost:6379/0",
"thread_name_generator": "graph.thread_name_generator:MyNameGenerator",
"rate_limit": {
"enabled": true,
"backend": "redis",
"requests": 100,
"window": 60,
"by": "user",
"trusted_proxy_headers": true,
"trusted_proxy_hops": 1,
"exclude_paths": ["/docs"],
"redis": { "url": "${REDIS_URL}", "prefix": "myapp:rate-limit" },
"fail_open": true
},
"websocket": { "max_connections": 500, "max_connections_per_user": 5 },
"ag_ui": { "enabled": false },
"observability": { "level": "standard", "logfire": { "enabled": false } },
"test": { "path": "tests", "coverage": true, "coverage_threshold": 80 },
"evaluation": { "directory": "evals", "output_dir": "eval_reports", "threshold": 0.75 }
}Frequently asked questions
- Which key is required in 10xgraph.json?
- Only agent, a string in module:attribute form that points at your compiled graph. Every other key is optional.
- Where does the CLI look for the config file?
- It searches the working directory and its parents for the path you pass with --config (default 10xgraph.json). With the default name, each directory is checked for 10xgraph.json first and the older agentflow.json second. Without a path, test and eval also try .agentflow.json and agentflow.config.json.
- Does agentflow.json still work?
- Yes, until 2.0. When 10xgraph.json is missing, the CLI and the server read agentflow.json from the same directory. Rename the file to 10xgraph.json when convenient; the keys are identical.