Skip to main content
When one agent can do the work, routing is easy. When ten agents can do the work differently, routing becomes a judgment problem. Some are faster. Some are cheaper. Some are overloaded. Some should decline the task entirely. Without a negotiation layer, orchestration becomes brittle. Tasks get sent to the wrong specialist, quality becomes inconsistent, and cost or latency starts to drift in ways that are hard to control.

Why Negotiation Matters

In a network of agents, selection should not depend on guesswork or static routing rules alone. An orchestrator needs a way to ask multiple agents, compare their fit, and choose the one most likely to succeed under the current constraints.
Static routingBindu negotiation
Predefined destination for each task typeDynamic agent selection based on real conditions
Limited awareness of load or costConsiders skill, performance, load, and cost
Hard to adapt when agent quality changesAgents continuously self-assess for each request
Good for simple fixed systemsBetter for evolving multi-agent networks
Failures often appear lateWeak fits can reject or score themselves lower early
That is the shift: Bindu lets orchestrators ask agents to evaluate themselves before assigning work, so selection becomes a transparent decision instead of a hidden assumption.
If multiple agents might complete the same task, the system should not rely on whichever one is listed first. It should ask who is actually best suited right now.

How Bindu Negotiation Works

Bindu’s negotiation system enables orchestrators to query multiple agents and select the best one for a task based on skills, performance, load, and cost.

The Negotiation Model

Bindu uses a simple decision pattern:
broadcast request -> self-assessment -> ranking -> selection
The model stays readable to developers while still giving agents room to make nuanced decisions:
  • The orchestrator asks multiple agents for an assessment
  • Each agent evaluates hard constraints and fit
  • The response returns acceptance, score, and reasoning
  • The orchestrator ranks responses and sends the task to the strongest match

Adaptive

Agent selection can change per request instead of being fixed in advance.

Explainable

Responses include scores, subscores, and skill reasoning rather than a black-box yes or no.

Efficient

Orchestrators can avoid weak matches early and send work to the best-fit agent faster.

The Lifecycle: Broadcast, Assess, Select

1

Broadcast

The orchestrator sends the same assessment request to multiple candidate agents.The request includes the task summary, input and output expectations, tool requirements, latency and cost constraints, and an optional scoring model.
POST /agent/negotiation
Content-Type: application/json

{
  "task_summary": "Extract tables from PDF invoices",
  "task_details": "Process invoice PDFs and extract structured data",
  "input_mime_types": ["application/pdf"],
  "output_mime_types": ["application/json"],
  "required_tools": ["pdf_parser"],
  "forbidden_tools": ["web_search"],
  "max_latency_ms": 5000,
  "max_cost_amount": "0.001",
  "min_score": 0.7,
  "weights": {
    "skill_match": 0.55,
    "io_compatibility": 0.20,
    "performance": 0.15,
    "load": 0.05,
    "cost": 0.05
  }
}
2

Assess

Each agent runs a self-assessment. It first checks hard constraints such as supported tools or input/output compatibility, then scores softer dimensions like fit, performance, load, and cost.The default weighted formula is:
score = (
    skill_match * 0.55 +        # Primary: capability matching
    io_compatibility * 0.20 +   # Input/output format support
    performance * 0.15 +        # Speed and reliability
    load * 0.05 +               # Current availability
    cost * 0.05                 # Pricing
)
An agent can reject cleanly on hard constraints, or accept and explain how strong the fit actually is.
3

Select

Agents return acceptance, score, confidence, and supporting reasoning. The orchestrator ranks the candidates and chooses the best one.
{
  "accepted": true,
  "score": 0.89,
  "confidence": 0.95,
  "skill_matches": [
    {
      "skill_id": "pdf-processing-v1",
      "skill_name": "PDF Processing",
      "score": 0.92,
      "reasons": [
        "semantic similarity: 0.95",
        "tags: pdf, tables, extraction",
        "capabilities: text_extraction, table_extraction"
      ]
    }
  ],
  "matched_tags": ["pdf", "tables", "extraction"],
  "matched_capabilities": ["text_extraction", "table_extraction"],
  "latency_estimate_ms": 2000,
  "queue_depth": 2,
  "subscores": {
    "skill_match": 0.92,
    "io_compatibility": 1.0,
    "performance": 0.85,
    "load": 0.90,
    "cost": 1.0
  }
}

Configuration

Enable Negotiation

config = {
    "name": "my_agent",
    "skills": ["skills/pdf-processing"],
    "negotiation": {
        "embedding_api_key": os.getenv("OPENROUTER_API_KEY"),
    }
}
When the embedding API key is present, skill matching uses semantic similarity in addition to exact tag matching.

Environment Variables

# Primary: auto-injected when negotiation capability is enabled
OPENROUTER_API_KEY=sk-or-v1-your-key-here

# Alternative: set directly via nested settings
NEGOTIATION__EMBEDDING_API_KEY=sk-or-v1-your-key-here

Negotiation Design Principles

Honest

Agents should score themselves realistically instead of over-claiming capability.

Weighted

Orchestrators can tune weights to favor quality, latency, load, or cost.

Composable

Negotiation fits naturally into orchestration layers that query many agents at once.

Real-World Use Cases

An orchestrator can query many translation agents at once, compare specialization and queue depth, and send the work to the strongest candidate.
# Query multiple translation agents
for agent in translation-agents:
  curl http://$agent:3773/agent/negotiation \
    -d '{"task_summary": "Translate technical manual to Spanish"}'

# Responses ranked by orchestrator:
# Agent 1: score=0.98 (technical specialist, queue=2)
# Agent 2: score=0.82 (general translator, queue=0)
# Agent 3: score=0.65 (no technical specialization)
Negotiation can be used to find the cheapest acceptable agent instead of simply the highest-quality one.
agents = [a for a in query_all_agents(task) if a.score > 0.8]
cheapest = min(agents, key=lambda a: a.cost)
Orchestrators can collect negotiation responses directly and apply their own business logic before assigning the final task.
import httpx

async def find_best_agent(task_summary, agent_urls):
    responses = []

    async with httpx.AsyncClient() as client:
        for url in agent_urls:
            try:
                resp = await client.post(
                    f"{url}/agent/negotiation",
                    json={"task_summary": task_summary}
                )
                if resp.status_code == 200:
                    responses.append({"url": url, "data": resp.json()})
            except Exception as e:
                print(f"Agent {url} failed: {e}")

    if not responses:
        return None

    best = max(responses, key=lambda r: r["data"]["score"])
    return best["url"]

best_agent = await find_best_agent(
    "Extract tables from PDF invoice",
    ["http://agent1:3773", "http://agent2:3773"]
)

Security Best Practices

Score Honestly

Agents should return realistic confidence and capability scores instead of inflating their fit.

Use Thresholds

Orchestrators should set minimum score thresholds and fallback paths instead of accepting every response.

Sunflower LogoBindu enables agents to negotiate like sunflowers — independent in stance, yet aligned in trust across the Internet of Agents.