Quickstart
In shortInstall 10xGraph, build a support agent in Python, serve it with the API server, then call it with curl and the TypeScript client.
- 4 min read
- 6 sections
- Updated
- v0.9.2
- Markdown
This page builds a working support agent with two tools, runs it from a Python script, serves it with the 10xGraph API server, then calls it with curl and from TypeScript. You need Python 3.12 or newer and a Google API key.
Install the packages
pip install "10xgraph[google-genai]" 10xgraph-api10xgraph is the framework, 10xgraph-api adds the server and the 10xgraph command, and the google-genai extra adds the model provider used below. Installation covers uv, other extras and provider API keys. The Google provider reads GEMINI_API_KEY or GOOGLE_API_KEY:
export GOOGLE_API_KEY="your-key"Build and run the agent
-
Write the agent
Create
agent.py. A tool is a plain Python function. The docstring and type hints become the schema the model sees.agent.py from tenxgraph.prebuilt.agent import ReactAgent from tenxgraph.storage.checkpointer import InMemoryCheckpointer def lookup_order(order_id: str) -> dict: """Look up an order by id and return its status and total.""" return {"order_id": order_id, "status": "delivered", "total": 59.0} def refund_order(order_id: str, amount: float) -> str: """Refund an order. This moves money, so it must run once per request.""" return f"Refunded {amount:.2f} for order {order_id}" agent = ReactAgent( model="google/gemini-2.5-flash", provider="google", system_prompt=[{"role": "system", "content": "You are a concise support agent for an online shop."}], tools=[lookup_order, refund_order], ) app = agent.compile(checkpointer=InMemoryCheckpointer())compile()returns aCompiledGraph. That object, namedapphere, is what you run and what the server loads. -
Run it from Python
Add a runner next to the agent.
run.py from tenxgraph.core.state import Message from agent import app result = app.invoke( {"messages": [Message.text_message("Where is order 1042?")]}, config={"thread_id": "quickstart-1"}, ) print(result["messages"][-1].text())Terminal python run.pyThe model decides to call
lookup_order, the tool node runs it, and the agent node writes the final answer. Ask it to refund an order and it callsrefund_orderthe same way. -
Add the config file
The server finds your graph through
10xgraph.json. Theagentvalue ismodule:variable.10xgraph.json { "agent": "agent:app", "env": ".env", "auth": null } -
Serve it
Terminal 10xgraph apiThe server listens on
127.0.0.1:8000by default. Use--host 0.0.0.0to accept outside connections and--portto change the port. -
Call it with curl
Terminal curl -X POST http://127.0.0.1:8000/v1/graph/invoke \ -H "Content-Type: application/json" \ -d '{ "messages": [ {"role": "user", "content": [{"type": "text", "text": "Where is order 1042?"}]} ], "config": {"thread_id": "quickstart-2"} }'The reply is wrapped in a
dataobject, next to ametadataobject with a request id and timestamp. The assistant message is the last item indata.messages.
Call it from TypeScript
10xgraph-client is a typed client for the endpoints 10xgraph api exposes: graph execution, threads, long-term memory and file uploads. It needs Node.js 18 or newer. With the server still running:
npm install 10xgraph-clientimport { AgentFlowClient, Message } from "10xgraph-client";
const client = new AgentFlowClient({ baseUrl: "http://127.0.0.1:8000" });
const result = await client.invoke(
[Message.text_message("Where is order 1042?")],
{
config: { thread_id: "quickstart-3" },
recursion_limit: 10,
}
);
console.log(result.messages.at(-1)?.text());If the server has auth enabled, pass auth: bearerAuth("your-api-token") to the constructor. The client also exports basicAuth(username, password) and headerAuth(name, value).
To stream the reply, iterate client.stream(...). It calls POST /v1/graph/stream:
import { StreamEventType } from "10xgraph-client";
const stream = client.stream(
[Message.text_message("Refund order 1042 for 59.00.")],
{ config: { thread_id: "quickstart-4" } }
);
for await (const chunk of stream) {
if (chunk.event === StreamEventType.MESSAGE && chunk.message) {
process.stdout.write(chunk.message.text());
}
}| Topic | Guide |
|---|---|
| Client setup, auth, config options | Create a client |
| Invoke, stream, WebSocket, partial results | Invoke an agent |
| Streaming responses in depth | Stream responses |
| Thread state, messages, history | Manage threads |
| Long-term memory store and search | Use memory API |
| File uploads and multimodal messages | Upload files |
| Remote tools from the client side | Register remote tools |
What does the request body accept?
The invoke endpoint validates the body against GraphInputSchema:
| Field | Default | Meaning |
|---|---|---|
messages |
[] |
Messages to process. Required unless you send resume. |
config |
none | Run settings. thread_id selects the conversation. |
initial_state |
none | Initial values for your state fields. |
recursion_limit |
25 | Step cap for the run. Allowed range is 1 to 100. |
response_granularity |
low |
low returns messages, partial adds context and summary, full adds state. |
resume |
none | Answer for a thread paused by an interrupt. |
Message content is a list of typed blocks, so a text message is [{"type": "text", "text": "..."}].
Where to go next
Frequently asked questions
- Do I need ReactAgent, or should I write a StateGraph myself?
- Start with ReactAgent. It builds the standard reason-and-act graph for you (one agent node, one tool node, a conditional edge between them) and returns a normal compiled graph. Move to StateGraph when you need custom routing or several agents.
- Can I use OpenAI or Anthropic instead of Google?
- Yes. Change the model string and the provider argument, and install the matching extra. The graph, the tools and the API server stay the same.
- Which Node.js version does the TypeScript client need?
- Node.js 18 or newer. Install it with npm install 10xgraph-client and point AgentFlowClient at the baseUrl of your running 10xgraph api server.
- How do I authenticate the TypeScript client?
- Pass an auth option to the AgentFlowClient constructor, for example bearerAuth("your-token"). The client also exports basicAuth(username, password) and headerAuth(name, value).
- Why does the second curl call remember the first one?
- Both calls send the same thread_id, and the compiled graph has a checkpointer. The checkpointer stores the conversation per thread, so the next call on that thread continues it.