Skip to content

Edges

Edges are the typed relationships between agents in a Claw society graph. They are first-class primitives -- not configuration, not metadata, not an afterthought. An edge determines what each agent can see, how events are routed between them, how conflicts are resolved, and when the interaction terminates.

In Claw SDK, the graph IS the program. Edges encode the semantics of collaboration.

What Is an Edge

An edge connects two or more agents and carries a type that defines concrete runtime behavior:

  • Visibility -- which artifacts and events each agent can see.
  • Event routing -- how messages flow between connected agents. Events travel along edges, not via global broadcast.
  • Conflict resolution -- how competing or contradictory outputs are reconciled.
  • Termination -- when the interaction along this edge is considered complete.

Every edge has a source and target (for binary edges) or a set of members (for group edges). The edge type -- Delegation, Oversight, Cooperation, Competition, or Coopetition -- determines the rules.

from claw import Society, Agent, Oversight

s = Society("code-review")
coder = Agent("coder", role="implementer", model="claude-sonnet")
reviewer = Agent("reviewer", role="critic", model="claude-sonnet")

# This edge IS the review relationship -- not just a link
s.connect(coder, reviewer, Oversight(max_rounds=3))

Agents referenced in connect() are automatically added to the society if not already present.

The Five Edge Types

Claw ships five built-in edge types, based on the collaboration taxonomy from Tran et al. (2025). Each type maps to a distinct pattern of multi-agent interaction.

Delegation

Task assignment from a delegator to a worker.

The delegator issues a task specification and instructions. The worker has full visibility into both. The delegator sees a progress summary. The interaction terminates when the worker reports complete or the delegator sends accept or reject.

Use Delegation when one agent is responsible for defining what needs to happen and another is responsible for doing it.

from claw import Society, Agent, Delegation

s = Society("task-pipeline")
pm = Agent("pm", role="project-manager", model="claude-sonnet")
coder = Agent("coder", role="implementer", model="claude-opus")

s.connect(pm, coder, Delegation())

Key configuration:

Field Type Default Description
escalation_policy EscalationPolicy \| None None Policy for escalating issues during delegation
from claw import Delegation, EscalationPolicy

s.connect(pm, coder, Delegation(
    escalation_policy=EscalationPolicy(to="tech-lead"),
))

Visibility rules: - Worker sees: full task spec, delegator instructions, shared artifacts - Delegator sees: progress summary

Termination: - Worker reports complete - Delegator sends accept or reject - max_rounds exceeded (if configured)

Oversight

Asymmetric review relationship.

The overseer has full visibility -- they see all artifacts and the overseen agent's work log. The overseen agent sees only feedback comments. The overseer adjudicates quality by approving or rejecting.

Use Oversight for code review, quality gates, editorial review, or any scenario where one agent evaluates another's output.

from claw import Society, Agent, Oversight

s = Society("review-gate")
coder = Agent("coder", role="implementer", model="claude-opus")
reviewer = Agent("reviewer", role="critic", model="claude-sonnet")

s.connect(coder, reviewer, Oversight(max_rounds=3))

Key configuration:

Field Type Default Description
max_rounds int \| None None Maximum review rounds before forced termination
on_deadlock EscalationPolicy \| Escalate \| None None What happens when max_rounds is reached without resolution
from claw import Oversight, EscalationPolicy
from claw.resolve import Escalate

s.connect(coder, reviewer, Oversight(
    max_rounds=3,
    on_deadlock=Escalate(to="tech-lead"),
))

Visibility rules: - Overseer sees: all artifacts, overseen agent's work log - Overseen agent sees: only feedback comments from the overseer

Termination: - Overseer sends approve or reject - max_rounds exceeded

Cooperation

Bidirectional transparent collaboration toward a shared goal.

Both agents have full visibility into all shared artifacts and each other's work log. Outputs are merged into the shared artifacts. Neither agent has an information advantage.

Use Cooperation for pair programming, co-authoring, joint design, or any scenario where agents work together as equals.

from claw import Society, Agent, Cooperation

s = Society("pair-programming")
frontend = Agent("frontend", role="frontend-dev", model="claude-sonnet")
backend = Agent("backend", role="backend-dev", model="claude-sonnet")

s.connect(frontend, backend, Cooperation(shared=["api-contract"]))

Key configuration:

Field Type Default Description
shared list[str] [] List of shared resource/topic identifiers that both agents have full visibility into

Visibility rules: - Both agents see: all shared artifacts, each other's work log - Fully symmetric -- no information asymmetry

Termination: - Both agents agree on completion - max_rounds exceeded (if configured)

Competition

Independent work with judge-based selection of the best output.

Competing agents are isolated -- they can see the task specification but not each other's work. A resolution strategy selects the winner after all agents submit.

Use Competition for competitive coding, A/B testing of approaches, red team/blue team exercises, or any scenario where you want diverse solutions evaluated against each other.

from claw import Society, Agent, Competition, JudgePicks

s = Society("competitive-coding")
coder1 = Agent("coder1", role="implementer", model="claude-opus")
coder2 = Agent("coder2", role="implementer", model="claude-opus")
coder3 = Agent("coder3", role="implementer", model="claude-sonnet")
reviewer = Agent("reviewer", role="evaluator", model="claude-sonnet")

s.compete(
    [coder1, coder2, coder3],
    Competition(resolve=JudgePicks(judge=reviewer)),
)

Key configuration:

Field Type Default Description
resolve ResolveStrategy (required) Strategy for selecting the winning submission. Competition edges without a resolve strategy are rejected at compile time.

Visibility rules: - Each competitor sees: task specification only - Competitors cannot see each other's work - Judge (if JudgePicks) sees: all submissions

Termination: - All competitors submit, then the resolution strategy runs - max_rounds exceeded (if configured)

Coopetition

Mixed cooperation and competition on different aspects.

Agents cooperate on shared interests (full visibility) and compete on conflicting interests (isolated). Resolution is domain-specific and applied only to the competitive aspects.

Use Coopetition for negotiation, standards development, cross-team integration, or any scenario where agents share some goals but compete on others.

from claw import Society, Agent, Coopetition, MajorityVote

s = Society("api-negotiation")
team_a = Agent("team-a", role="api-designer", model="claude-sonnet")
team_b = Agent("team-b", role="api-designer", model="claude-sonnet")

s.negotiate(
    [team_a, team_b],
    Coopetition(
        cooperate_on=["shared-api"],
        compete_on=["implementation"],
        resolve=MajorityVote(),
    ),
)

Key configuration:

Field Type Default Description
cooperate_on list[str] [] Aspects where agents share information freely
compete_on list[str] [] Aspects where agents work independently
resolve ResolveStrategy (required) Strategy for resolving competitive aspects

Visibility rules: - On cooperate_on topics: full mutual visibility (like Cooperation) - On compete_on topics: isolated (like Competition)

Termination: - Cooperative aspects reach agreement, competitive aspects are resolved - max_rounds exceeded (if configured)

Group Edges

Some edge types have natural N-ary semantics -- they connect more than two agents at once. Claw calls these group edges (or hyperedges).

Three edge types support group semantics:

Edge Type Group Method Example
Competition society.compete() Tournament with N entrants
Cooperation society.cooperate() N agents sharing an artifact
Coopetition society.negotiate() Multi-party negotiation

Two edge types are binary only:

Edge Type Method Why
Delegation society.connect() Task assignment is inherently one-to-one
Oversight society.connect() Review is inherently between overseer and overseen

Using group edges

Group edges require at least 2 members. Members must be unique (no duplicates). All member agents are automatically added to the society.

from claw import Society, Agent, Competition, Cooperation, JudgePicks

s = Society("multi-agent")
a = Agent("a", role="developer", model="claude-sonnet")
b = Agent("b", role="developer", model="claude-sonnet")
c = Agent("c", role="developer", model="claude-sonnet")
judge = Agent("judge", role="evaluator", model="claude-sonnet")

# 3-way competition
s.compete([a, b, c], Competition(resolve=JudgePicks(judge=judge)))

# 3-way cooperation
s.cooperate([a, b, c], Cooperation(shared=["design-doc"]))

Attempting to use a binary-only type with a group edge will raise a ValueError:

# This will raise ValueError at construction time
from claw.edge import GroupEdge
GroupEdge(members=[a, b, c], type=Delegation())  # ValueError!

Edge Configuration (Shared Fields)

All edge types inherit from EdgeType and share these configuration fields:

Field Type Default Description
artifacts list[Artifact] [] Artifacts that flow along this edge
events list[str] [] Allowed event types on this edge (extensible strings)
max_rounds int \| None None Maximum interaction rounds before termination
timeout timedelta \| None None Wall-clock timeout per round
on_timeout TimeoutPolicy ESCALATE Policy when a round times out

Timeout policies

The on_timeout field accepts a TimeoutPolicy enum with three options:

Policy Behavior
TimeoutPolicy.ESCALATE Route the timeout to an upstream agent for resolution (default)
TimeoutPolicy.RETRY_ONCE Retry the timed-out operation exactly once
TimeoutPolicy.TERMINATE Stop execution on the affected edge immediately
from datetime import timedelta
from claw import Oversight, TimeoutPolicy

s.connect(coder, reviewer, Oversight(
    max_rounds=3,
    timeout=timedelta(minutes=5),
    on_timeout=TimeoutPolicy.TERMINATE,
))

Attaching artifacts to edges

Artifacts can be attached to edges so they flow along the relationship. This is how agents share work products.

from claw import Cooperation, StringArtifact

spec = StringArtifact(name="api-spec", max_tokens=8000)

s.connect(frontend, backend, Cooperation(
    shared=["api-contract"],
    artifacts=[spec],
))

When to Use Each Type

Use this decision matrix to pick the right edge type for your scenario:

Scenario Edge Type Why
Manager assigns work to developer Delegation One-way task flow with accept/reject
Code review Oversight Asymmetric visibility -- reviewer sees all, author sees feedback
Pair programming Cooperation Full mutual visibility, shared output
Competitive coding challenge Competition Isolated work, judged result
API negotiation between teams Coopetition Cooperate on interface, compete on implementation
Editorial review of a document Oversight Editor adjudicates quality
Brainstorming with equal peers Cooperation No hierarchy, full sharing
Red team vs. blue team Competition Adversarial isolation is the point
Standards committee Coopetition Shared goals with competing proposals

Rules of thumb:

  • If one agent defines the task and another executes it, use Delegation.
  • If one agent evaluates another's work, use Oversight.
  • If agents work together as equals, use Cooperation.
  • If agents should not see each other's work, use Competition.
  • If agents share some context but compete on specific outputs, use Coopetition.

Resolution Strategies

Competition and Coopetition edges require a resolution strategy -- a mechanism for selecting among competing outputs. Claw provides three built-in strategies.

JudgePicks

A designated judge agent evaluates all submissions and picks a winner.

from claw import Agent, Competition, JudgePicks

judge = Agent("judge", role="evaluator", model="claude-sonnet")

Competition(
    resolve=JudgePicks(
        judge=judge,
        criteria=["correctness", "readability", "performance"],
        on_neither="escalate",
    ),
)
Field Type Default Description
judge Agent (required) The agent that evaluates submissions
criteria list[str] [] Evaluation criteria (e.g., ["correctness", "performance"])
output_schema JsonSchema {"winner": str, "rationale": str} JSON Schema for the judge's structured output
on_neither str "escalate" Policy when no submission meets criteria ("escalate", "retry", "best_effort")

MajorityVote

Multiple voter agents each cast a vote. The submission with the most votes wins.

from claw import Agent, Competition, MajorityVote

voter1 = Agent("voter1", role="reviewer", model="claude-sonnet")
voter2 = Agent("voter2", role="reviewer", model="claude-sonnet")
voter3 = Agent("voter3", role="reviewer", model="claude-sonnet")

Competition(
    resolve=MajorityVote(voters=[voter1, voter2, voter3]),
)
Field Type Default Description
voters list[Agent] [] Agents that participate in voting

Escalate

Escalate to a designated agent for resolution. Typically used as a fallback when automated resolution fails (deadlock, all submissions rejected, etc.).

from claw import Oversight
from claw.resolve import Escalate

s.connect(coder, reviewer, Oversight(
    max_rounds=3,
    on_deadlock=Escalate(to="tech-lead", summary=True),
))
Field Type Default Description
to str (required) Name of the agent to escalate to
summary bool True Whether to include a summary of the situation

Custom strategies

Any object that satisfies the ResolveStrategy protocol can be used as a resolution strategy. The protocol is defined as a runtime-checkable Protocol class, so you can implement your own strategies by conforming to the interface.

Querying Edges

Once you have built a society, you can inspect its edges:

# All binary edges
s.edges

# All group edges
s.group_edges

# All edges (binary + group)
s.all_edges

# Edges involving a specific agent
s.edges_of(coder)

# Find a binary edge between two agents
s.edge_between(coder, reviewer)

Complete Example

Here is a full example that uses multiple edge types in a single society:

from claw import (
    Agent,
    Competition,
    Cooperation,
    Delegation,
    JudgePicks,
    Oversight,
    Society,
)

# Create the society
s = Society("software-team", description="A complete software development team")

# Define agents
pm = Agent("pm", role="project-manager", model="claude-sonnet")
arch = Agent("architect", role="system-architect", model="claude-opus")
dev1 = Agent("dev1", role="developer", model="claude-sonnet")
dev2 = Agent("dev2", role="developer", model="claude-sonnet")
reviewer = Agent("reviewer", role="code-reviewer", model="claude-sonnet")

# PM delegates work to the architect
s.connect(pm, arch, Delegation())

# Architect and PM cooperate on system design
s.connect(arch, pm, Cooperation(shared=["architecture-doc"]))

# Two developers compete on implementation
s.compete(
    [dev1, dev2],
    Competition(
        resolve=JudgePicks(
            judge=reviewer,
            criteria=["correctness", "test-coverage", "readability"],
        ),
    ),
)

# Reviewer oversees the winning implementation
s.connect(dev1, reviewer, Oversight(max_rounds=3))
s.connect(dev2, reviewer, Oversight(max_rounds=3))

print(f"Society '{s.name}' has {len(s.agents)} agents and {len(s.all_edges)} edges")