Agent Shared State
Give your AI agents shared state. Copy, paste, run.
If you want the installation guide for Claude, Codex, ChatGPT, Cursor, and Continue, see INSTALL.md.
How it works
Section titled “How it works”- Define — Register
save_stateandread_stateas tools your LLM can call. - Handle — When the LLM calls a tool, your handler sends the request to the echoValue API.
- Share — Any agent with the same token can read and write. Shared state, zero config.
Full example
Section titled “Full example”# pip install anthropic requests
import requestsfrom anthropic import Anthropic
# Get a free token: curl https://api.echovalue.dev/token -d 'token=new'TOKEN = "your-echovalue-token"BASE = "https://api.echovalue.dev/kv"
# 1. Define the toolstools = [ { "name": "save_state", "description": "Save a key-value pair to shared agent state", "input_schema": { "type": "object", "properties": { "group": {"type": "string", "description": "Namespace / bucket"}, "key": {"type": "string", "description": "Identifier"}, "value": {"type": "string", "description": "Data to store"}, "ttl": {"type": "integer", "description": "Expiry in seconds"} }, "required": ["group", "key", "value"] } }, { "name": "read_state", "description": "Read a value from shared agent state", "input_schema": { "type": "object", "properties": { "group": {"type": "string", "description": "Namespace / bucket"}, "key": {"type": "string", "description": "Identifier"} }, "required": ["group", "key"] } }]
# 2. Handle tool calls → echoValue APIdef run_tool(name, args): headers = {"x-token": TOKEN} if name == "save_state": ttl = args.get("ttl", 86400) r = requests.post( f"{BASE}/{args['group']}/{args['key']}?ttl={ttl}", data=args["value"], headers=headers) return r.text if name == "read_state": r = requests.get( f"{BASE}/{args['group']}/{args['key']}", headers=headers) return r.text
# 3. Run the agentclient = Anthropic()response = client.messages.create( model="claude-sonnet-4-5", max_tokens=1024, tools=tools, messages=[{"role": "user", "content": "Save status=done for the import pipeline"}])
# 4. Process tool calls from the responsefor block in response.content: if block.type == "tool_use": result = run_tool(block.name, block.input) print(f"{block.name} → {result}") # save_state → OK// npm install @anthropic-ai/sdk
import Anthropic from "@anthropic-ai/sdk";
// Get a free token: curl https://api.echovalue.dev/token -d 'token=new'const TOKEN = "your-echovalue-token";const BASE = "https://api.echovalue.dev/kv";
// 1. Define the toolsconst tools: Anthropic.Tool[] = [ { name: "save_state", description: "Save a key-value pair to shared agent state", input_schema: { type: "object" as const, properties: { group: { type: "string", description: "Namespace / bucket" }, key: { type: "string", description: "Identifier" }, value: { type: "string", description: "Data to store" }, ttl: { type: "integer", description: "Expiry in seconds" }, }, required: ["group", "key", "value"], }, }, { name: "read_state", description: "Read a value from shared agent state", input_schema: { type: "object" as const, properties: { group: { type: "string", description: "Namespace / bucket" }, key: { type: "string", description: "Identifier" }, }, required: ["group", "key"], }, },];
// 2. Handle tool calls → echoValue APIasync function runTool(name: string, args: Record<string, any>) { const headers = { "x-token": TOKEN };
if (name === "save_state") { const ttl = args.ttl ?? 86400; const res = await fetch( `${BASE}/${args.group}/${args.key}?ttl=${ttl}`, { method: "POST", body: args.value, headers } ); return res.text(); }
if (name === "read_state") { const res = await fetch( `${BASE}/${args.group}/${args.key}`, { headers } ); return res.text(); }}
// 3. Run the agentconst client = new Anthropic();const response = await client.messages.create({ model: "claude-sonnet-4-5", max_tokens: 1024, tools, messages: [{ role: "user", content: "Save status=done for the import pipeline" }],});
// 4. Process tool calls from the responsefor (const block of response.content) { if (block.type === "tool_use") { const result = await runTool(block.name, block.input as Record<string, any>); console.log(`${block.name} → ${result}`); // save_state → OK }}