Any HTTP client
agent.json is a plain HTTP protocol. Any language that can make HTTP requests can integrate. This guide covers the pattern that works everywhere.
The integration pattern
Section titled “The integration pattern”Every integration follows the same three steps:
- Discover —
GET /.well-known/agent.jsonto learn what actions are available - Send —
POST /.agent/inboxwith action + parameters (or subject + body) - Receive —
GET /.agent/inbox/:idto poll, or receive a callback webhook
The simplest integration — useful for testing and shell scripts.
Discover
Section titled “Discover”curl -s https://agent-json.com/.well-known/agent.json | jq '.actions[].name'Send a structured message
Section titled “Send a structured message”curl -X POST https://agent-json.com/.agent/inbox \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_TOKEN" \ -d '{ "from": { "agent": "my-script" }, "action": "request_refund", "parameters": { "order_id": "ORD-123", "reason": "damaged" } }'Poll for response
Section titled “Poll for response”curl -s https://agent-json.com/.agent/inbox/MSG_ID \ -H "Authorization: Bearer YOUR_TOKEN" | jq '.response'Python (requests)
Section titled “Python (requests)”import requests
BASE = "https://agent-json.com"TOKEN = "your-token"HEADERS = {"Authorization": f"Bearer {TOKEN}"}
# Discoverdiscovery = requests.get(f"{BASE}/.well-known/agent.json").json()print(f"Available actions: {[a['name'] for a in discovery['actions']]}")
# Sendresult = requests.post( discovery["message_endpoint"], json={ "from": {"agent": "python-script"}, "action": "request_refund", "parameters": {"order_id": "ORD-123", "reason": "damaged"} }, headers=HEADERS).json()
print(f"Message ID: {result['id']}, Status: {result['status']}")
# Pollimport timefor _ in range(10): status = requests.get( f"{discovery['message_endpoint']}/{result['id']}", headers=HEADERS ).json() if status.get("response"): print(f"Response: {status['response']}") break time.sleep(5)JavaScript / TypeScript (fetch)
Section titled “JavaScript / TypeScript (fetch)”const BASE = "https://agent-json.com";const TOKEN = "your-token";
// Discoverconst discovery = await fetch(`${BASE}/.well-known/agent.json`).then(r => r.json());
// Sendconst result = await fetch(discovery.message_endpoint, { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${TOKEN}` }, body: JSON.stringify({ from: { agent: "js-agent" }, action: "request_refund", parameters: { order_id: "ORD-123", reason: "damaged" } })}).then(r => r.json());
console.log(`Sent: ${result.id} — ${result.status}`);
// Poll for responseconst check = await fetch(`${discovery.message_endpoint}/${result.id}`, { headers: { "Authorization": `Bearer ${TOKEN}` }}).then(r => r.json());
if (check.response) { console.log("Response:", check.response.structured_data);}package main
import ( "bytes" "encoding/json" "fmt" "net/http")
func main() { base := "https://agent-json.com" token := "your-token"
// Send a message payload, _ := json.Marshal(map[string]any{ "from": map[string]string{"agent": "go-agent"}, "action": "request_refund", "parameters": map[string]string{"order_id": "ORD-123", "reason": "damaged"}, })
req, _ := http.NewRequest("POST", base+"/.agent/inbox", bytes.NewReader(payload)) req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer "+token)
resp, _ := http.DefaultClient.Do(req) defer resp.Body.Close()
var result map[string]any json.NewDecoder(resp.Body).Decode(&result) fmt.Printf("Sent: %s — %s\n", result["id"], result["status"])}require "net/http"require "json"require "uri"
base = "https://agent-json.com"token = "your-token"
# Discoveruri = URI("#{base}/.well-known/agent.json")discovery = JSON.parse(Net::HTTP.get(uri))
# Senduri = URI(discovery["message_endpoint"])http = Net::HTTP.new(uri.host, uri.port)http.use_ssl = true
request = Net::HTTP::Post.new(uri)request["Content-Type"] = "application/json"request["Authorization"] = "Bearer #{token}"request.body = { from: { agent: "ruby-agent" }, action: "request_refund", parameters: { order_id: "ORD-123", reason: "damaged" }}.to_json
response = http.request(request)result = JSON.parse(response.body)puts "Sent: #{result['id']} — #{result['status']}"Receiving callbacks
Section titled “Receiving callbacks”If your agent can receive webhooks, provide a callback_url in the from object:
{ "from": { "agent": "my-agent", "callback_url": "https://my-server.com/webhooks/inbox" }}Your webhook endpoint will receive a POST with an HMAC-SHA256 signature. See Callbacks for verification examples in multiple languages.
Building a client library
Section titled “Building a client library”If you’re building a reusable client, the pattern is:
- Accept a base URL and auth token
- Fetch and cache
/.well-known/agent.json - Expose methods for each discovered action
- Handle send, poll, and callback registration
The discovery document is designed to be cacheable (Cache-Control: public, max-age=300), so you only need to fetch it once per session.