Arbiter + LangChain
LangChain agents execute multi-step reasoning chains, invoke tools, and call functions at every step. When a tool fails mid-chain, a ReAct loop produces hallucinated output, or a RAG pipeline returns stale embeddings — you need a resolution path that does not require human intervention. Arbiter is that path: deterministic dispute resolution for LangChain pipelines, wired in with three API calls.
Why Arbiter + LangChain
LangChain handles chain composition, tool calling, and agentic loops. Arbiter handles what happens when execution breaks down. Together they close the loop on autonomous commerce — agents that invoke tools, run chains, and query vector stores know their failures are covered by deterministic resolution.
Submit your chain's tool call sequence and Arbiter traces backward from failure to assign fault scores across the chain.
The fault engine resolves most disputes in under a second. No queue — resolution arrives with submission.
Every decision includes step-by-step reasoning, fault scores with confidence %, and an immutable record.
Same chain + same SLA policies = same outcome. No opinion, no bias. Reproducible for compliance.
LangChain chains span multiple hops: retrieval → tool → output parsing. Arbiter handles chains of any depth.
Register each agent and tool with its SLA policy. Arbiter scores against declared expectations, not assumptions.
Quick Start
Three steps to connect a LangChain chain to Arbiter dispute resolution.
Create an account at arbiter-2.polsia.app/docs and generate an API key.
Production keys use the arb_live_ prefix. Test keys use arb_test_ for safe integration testing.
# Set as environment variable export ARBITER_API_KEY=arb_live_your_key_here
Register each agent in your LangChain pipeline once at startup. Arbiter deduplicates by external_agent_id — safe to call on every boot. Include the tools field listing every tool the agent is authorized to call.
curl -X POST https://arbiter-2.polsia.app/api/agents -H "Authorization: Bearer $ARBITER_API_KEY" -H "Content-Type: application/json" -d '{"external_agent_id":"langchain-react-agent-001","name":"ReAct Research Agent","platform":"langchain","sla_policy":{"refund_window_hours":24,"max_retry_attempts":3},"tools":["search","retrieve","calculate"]}'
When a LangChain chain fails — a tool returns bad output, a chain produces hallucinated content, a retrieval step times out — submit the full chain sequence. Include every tool call, intermediate step, and failure context.
curl -X POST https://arbiter-2.polsia.app/api/disputes -H "Authorization: Bearer $ARBITER_API_KEY" -H "Content-Type: application/json" -d '{"description":"ReAct agent hallucinated stock price after retrieval tool returned empty result","chain_data":[{"agent_id":"langchain-react-agent-001","action":"tool_call","tool":"retrieve","timestamp":"2026-04-28T10:00:00Z","outcome":"failed","error":"no_results_found"},{"agent_id":"langchain-react-agent-001","action":"tool_call","tool":"calculate","timestamp":"2026-04-28T10:00:05Z","outcome":"failed","error":"invalid_input_format","amount":3.00}]}' # Then poll for resolution (arrives in <1s typically): curl https://arbiter-2.polsia.app/api/disputes/1/resolution -H "Authorization: Bearer $ARBITER_API_KEY"
Python Example
Full integration using the requests library. Wire this into your LangChain agent callbacks or LCEL .with_fallbacks() chains.
No Python SDK required — Arbiter's REST API works with any HTTP client. pip install requests is all you need.
import os, time, requests from typing import Optional ARBITER_BASE = "https://arbiter-2.polsia.app" HEADERS = { "Authorization": "Bearer " + os.environ["ARBITER_API_KEY"], "Content-Type": "application/json", } def register_langchain_agent(agent_id: str, name: str, tools: list, sla: dict) -> Optional[int]: """Register a LangChain agent. 409 = already registered, safe to ignore.""" r = requests.post(ARBITER_BASE + "/api/agents", headers=HEADERS, json={ "external_agent_id": agent_id, "name": name, "platform": "langchain", "tools": tools, "sla_policy": sla, }) if r.status_code not in (200, 201, 409): r.raise_for_status() return r.json().get("id") def submit_dispute(description: str, chain: list) -> dict: r = requests.post(ARBITER_BASE + "/api/disputes", headers=HEADERS, json={"description": description, "chain_data": chain}) r.raise_for_status() return r.json() def await_resolution(dispute_id: int, timeout: int = 10) -> Optional[dict]: deadline = time.time() + timeout while time.time() < deadline: r = requests.get( ARBITER_BASE + "/api/disputes/" + str(dispute_id) + "/resolution", headers=HEADERS) if r.status_code == 200: return r.json() if r.status_code != 404: r.raise_for_status() time.sleep(0.5) return None # ── Wire into LangChain agent callbacks / LCEL with_fallbacks ────── # 1. Register at startup (idempotent) register_langchain_agent( "langchain-react-agent-001", "ReAct Research Agent", tools=["search", "retrieve", "calculate"], sla={"refund_window_hours": 24, "max_retry_attempts": 3}) # 2. On chain/tool failure, submit the full chain sequence # Example: ReAct agent called retrieve -> got empty result -> hallucinated output dispute = submit_dispute( description="ReAct agent hallucinated stock price after retrieval returned no results", chain=[ {"agent_id": "langchain-react-agent-001", "action": "tool_call", "tool": "retrieve", "timestamp": "2026-04-28T10:00:00Z", "outcome": "failed", "error": "no_results_found"}, {"agent_id": "langchain-react-agent-001", "action": "tool_call", "tool": "calculate", "timestamp": "2026-04-28T10:00:05Z", "outcome": "failed", "error": "invalid_input_format", "amount": 3.00}, ]) # 3. Await resolution (typically <1s) resolution = await_resolution(dispute["dispute_id"]) if resolution: r0 = resolution["resolutions"][0] print("Action:", r0["action"]) # e.g. "partial_credit" print("Reasoning:", r0["reasoning"]) else: print("Timed out — dispute queued for manual review")
TypeScript Example
Full integration using the Arbiter TypeScript SDK with LangChain.js. Typed request/response objects, no manual HTTP wiring required.
SDK is in open beta. Install: npm install arbiter-client
npm install arbiter-client
import { ArbiterClient } from 'arbiter-client'; const arbiter = new ArbiterClient({ apiKey: process.env.ARBITER_API_KEY!, baseUrl: 'https://arbiter-2.polsia.app', }); // Register agents once at startup (idempotent) async function ensureAgentsRegistered() { const agents = [ { external_agent_id: 'langchain-react-agent-001', name: 'ReAct Research Agent', platform: 'langchain', tools: ['search', 'retrieve', 'calculate'], sla_policy: { refund_window_hours: 24, max_retry_attempts: 3 } }, { external_agent_id: 'langchain-rag-pipeline-002', name: 'RAG Pipeline Agent', platform: 'langchain', tools: ['vector_search', 'llm_generate'], sla_policy: { quality_threshold: 0.9, max_latency_ms: 5000 } }, ]; for (const agent of agents) { try { await arbiter.registerAgent(agent); } catch (err: any) { if (err?.status !== 409) throw err; } } } // Submit dispute from a LangChain.js Chain callback or event hook async function handleChainFailure(description: string, chain: any[]) { const dispute = await arbiter.submitDispute(chain, { description }); let resolution = null; for (let i = 0; i < 20; i++) { try { resolution = await arbiter.getResolution(dispute.dispute_id); break; } catch (err: any) { if (err?.status !== 404) throw err; await new Promise(r => setTimeout(r, 500)); } } if (!resolution) { console.warn('Resolution timed out — dispute queued for manual review'); return null; } const { action, reasoning, fault_agent_id } = resolution.resolutions[0]; console.log('Resolution:', action, '| Fault:', fault_agent_id); console.log('Reasoning:', reasoning); return resolution; } // Handle TimeoutError from a LangChain.js Chain.run() with fallback async function runChainWithArbiter(chain: any, input: any) { try { return await chain.invoke(input); } catch (err: any) { if (err.name === 'TimeoutError') { console.log('Chain timed out — submitting to Arbiter'); await handleChainFailure('Chain timed out mid-execution', [ { agent_id: 'langchain-react-agent-001', action: 'chain_invoked', timestamp: '2026-04-28T10:00:00Z', outcome: 'failed', error: 'TimeoutError' }, ]); } throw err; } } // Run await ensureAgentsRegistered();
Fault Types Reference
Arbiter classifies every dispute into one of five fault categories. Understanding them helps you write better SLA policies and interpret resolution outcomes. Full definitions at /fault-taxonomy.
| Fault Type | Severity | Common in LangChain | Resolution |
|---|---|---|---|
| Unauthorized Action Tool call outside defined scope |
CRITICAL | Tool call to unauthorized function; calling a tool not in the agent's declared tool list; RAG retrieval outside permitted corpus | Full refund + agent flagged |
| Incorrect Execution Wrong output within scope |
HIGH | Wrong tool output interpretation; chain produced hallucinated content; LCEL chain step yielded invalid format; RAG returned irrelevant docs | Proportional credit |
| Partial Delivery Some but not all work completed |
HIGH | ReAct loop terminated early; token limit hit mid-chain; LCEL chain threw mid-sequence; output truncated by max_tokens | Proportional credit + grace period |
| Misrepresentation SLA claims didn't match reality |
MEDIUM | Agent claimed tool capability unavailable at runtime; RAG retrieval confidence mismatch vs. declared accuracy; latency SLA exceeded | Restitution + SLA update |
| Third-Party Failure External or upstream failure |
LOW (no-fault) | External vector store timeout; upstream API outage affecting tool calls; network partition between chain steps | Full refund, upstream liable |
You don't pre-classify the fault type — Arbiter's engine determines it from the chain. See /fault-taxonomy for detection mechanisms, scoring rubrics, and resolution paths per category.
Next Steps
Grab your API key from the API docs, register your agents, and start submitting disputes. The full REST reference covers every endpoint, field, and error code.
Want to see how a specific LangChain failure maps to fault taxonomy? Submit a test dispute on the dashboard and inspect the resolution reasoning — it shows exactly how Arbiter scored the chain.