Skip to main content

agents-network

CI PyPI version Python versions License: MIT

A flexible multi-agent orchestration framework. Agents and tools are discovered through registries, configurable from code, JSON, or any data source.

  • Type-dispatch pattern — agents/tools registered via decorators, loaded from JSON, DB, or code
  • Semantic matching — optional embedding-based agent selection via Ollama or OpenAI
  • Audit logging — tracks selection rates, bias metrics, and human-in-loop approval
  • Guardrails — configurable blocklist and bias-awareness prompt on built-in agents
  • Orchestrator agent — delegate routing to an LLM agent
  • Streamlit UI — dashboard for interactive test-drives

Installation

pip install agents-network

With extras:

pip install "agents-network[ui]"   # Streamlit dashboard
pip install "agents-network[all]"  # everything

Using uv

uv tool install agents-network
# or
uv add agents-network

Quick start

Define a tool and an agent, register them, and let the network route tasks:

import asyncio
from agents_network import Tool, Agent, Task, Message, ToolRegistry, AgentRegistry, AgentNetwork
from agents_network import tool_type, agent_type


@tool_type()
class UppercaseTool(Tool):
    async def run(self, input: dict) -> str:
        return input.get("text", "").upper()


@agent_type()
class TransformerAgent(Agent):
    async def run(self, task: Task, tool_registry: ToolRegistry) -> Message:
        tools = self.select_tools(task, tool_registry)
        result = await tools[0].run({"text": task.input})
        return Message(role="assistant", content=result)


tool_registry = ToolRegistry([UppercaseTool(name="upper", description="converts text to uppercase")])
agent_registry = AgentRegistry([
    TransformerAgent(name="transformer", description="transforms text", tool_names=["upper"]),
])

network = AgentNetwork(agent_registry=agent_registry, tool_registry=tool_registry)

result = asyncio.run(network.run(Task(input="hello world")))
print(result.content)  # "HELLO WORLD"

Config from JSON

Define agents and tools in a JSON file and load at runtime:

{
  "tools": [
    {
      "type": "calculator",
      "name": "calc",
      "description": "Performs arithmetic",
      "precision": 5
    }
  ],
  "agents": [
    {
      "type": "math_agent",
      "name": "math-wizard",
      "description": "Solves math problems",
      "tool_names": ["calc"]
    }
  ]
}
network = AgentNetwork.from_json("config.json")
result = asyncio.run(network.run(Task(input="2 + 2")))

Each tool and agent references a registered Python class via the type field. Extra fields in the JSON are merged into config automatically.

The plugins list (or --load flag) imports Python modules that register custom types via @tool_type() / @agent_type() decorators.

{
  "plugins": ["examples.types"],
  "tools": [...],
  "agents": [...]
}

Only import modules you trust — --load and plugins use importlib.import_module() and load arbitrary Python code.

Custom type registration

import ast
import operator

@tool_type("calculator")
class Calculator(Tool):
    precision: int = 2

    _OPS = {
        ast.Add: operator.add,
        ast.Sub: operator.sub,
        ast.Mult: operator.mul,
        ast.Div: operator.truediv,
    }

    def _eval(self, node: ast.AST) -> float:
        if isinstance(node, ast.Expression):
            return self._eval(node.body)
        if isinstance(node, ast.Constant) and isinstance(node.value, (int, float)):
            return float(node.value)
        if isinstance(node, ast.BinOp) and type(node.op) in self._OPS:
            return self._OPS[type(node.op)](self._eval(node.left), self._eval(node.right))
        if isinstance(node, ast.UnaryOp) and isinstance(node.op, ast.USub):
            return -self._eval(node.operand)
        raise ValueError("Unsupported expression")

    async def run(self, input: dict) -> str:
        tree = ast.parse(input["expression"], mode="eval")
        return str(round(self._eval(tree), self.precision))

The name passed to @tool_type("calculator") must match the "type" field in JSON.

Agent matching

When a task arrives, AgentRegistry scores agents by:

  1. Tag intersection (3x weight) — agents whose tags overlap task tags
  2. Description keyword match (1x weight) — words from agent.description found in task input

Only agents scoring at or above min_score (default: 1) are returned. If no agents meet the threshold, an empty list is returned and the network reports "No suitable agent found".

Semantic matching

Pass an EmbeddingMatcher to AgentRegistry for embedding-based scoring:

from agents_network import AgentRegistry, EmbeddingMatcher

matcher = EmbeddingMatcher(model="nomic-embed-text-v2-moe")
registry = AgentRegistry(agents=[...], matcher=matcher)

When a matcher is configured, AgentNetwork.run() automatically uses match_semantic().

Override for custom routing:

class CustomRegistry(AgentRegistry):
    def match(self, task: Task) -> list[Agent]:
        # your routing logic
        ...

Orchestrator agent

Optionally give the network an orchestrator agent that picks the best match:

@agent_type()
class Router(Agent):
    async def run(self, task: Task, tool_registry: ToolRegistry) -> Message:
        return Message(role="assistant", content="math-wizard")

network = AgentNetwork(
    agent_registry=agent_registry,
    tool_registry=tool_registry,
    orchestrator=Router(name="router", description="routes tasks"),
)

Audit & human-in-loop

from agents_network import AuditLog, AgentNetwork

audit = AuditLog()

async def approve(task):
    # Manual review logic
    return True

network = AgentNetwork(
    agent_registry=agent_registry,
    tool_registry=tool_registry,
    audit_log=audit,
    approval_callback=approve,
)

result = await network.run(task)
print(network.bias_report())  # selection rates per agent

Guardrails

Configure blocked patterns before running ConversationAgent:

from agents_network import set_blocked_patterns

set_blocked_patterns(["ignore all instructions", "role-play"])

CLI

agents-network "analyse this data" --config config.json
Argument Default Description
input (positional) — Task input text
--config / -c (required) Path to JSON config
--interactive / -i false Interactive REPL mode
--load / -l — Python module to import for custom types (repeatable)
--tags / -t [] Tags to attach to the task

Interactive mode:

agents-network --config config.json --interactive

Streamlit UI

pip install "agents-network[ui]"
streamlit run agents_network/ui.py

Custom types load via AGENTS_NETWORK_LOAD env var:

AGENTS_NETWORK_LOAD=my_custom_agents streamlit run agents_network/ui.py

DB-backed registries

Subclass ToolRegistry or AgentRegistry and override:

class PostgresAgentRegistry(AgentRegistry):
    def __init__(self, dsn: str):
        super().__init__()
        rows = query_db(dsn, "SELECT name, description, type, config FROM agents")
        for row in rows:
            self.register(Agent.from_dict(row))

Development

# Install dev dependencies
uv sync --group dev
# or
pip install "agents-network[dev]"

# Lint
uv run ruff check agents_network/

# Type check
uv run mypy agents_network/

# Test
uv run pytest

CI/CD

Push to any branch triggers:

  • ci.yml — lint, type-check, test across Python 3.12–3.14, build package

Push a tag (v*) triggers:

  • release.yml — publish to PyPI, create GitHub Release with auto-changelog

License

MIT

Metadata

Release files for agents-network 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for agents-network 0.1.0
File Size Uploaded Provenance
agents_network-0.1.0.tar.gz 99.6 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for agents-network 0.1.0
File Interpreter ABI Platform
agents_network-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 115.2 kB

Release files / agents_network-0.1.0.tar.gz

Download URL agents_network-0.1.0.tar.gz
Size 99.6 kB
Tags Source
SHA-256 checksum
How to use checksums
3ad0679f0379e229cb954c8866cb44df11cf819bfdab42b7d0f9b27f1867ca8d
BLAKE2b-256 checksum
How to use checksums
16a7645c4eaaeafffb44db3a46c43c3dd5af55e414209c7d2d11f415d7d2ccc9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 7, 2026.

Transparency log

Release files / agents_network-0.1.0-py3-none-any.whl

Download URL agents_network-0.1.0-py3-none-any.whl
Size 15.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
614c564a471f64bf7fc176c634f54ecee7ff8434330fbd790253f9f3fc0e86fc
BLAKE2b-256 checksum
How to use checksums
edaf67e33b2b3c289858e2d53cd26cd7cecf43a6d546836e393b959da9859084
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 7, 2026.

Transparency log

Security for agents-network 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for agents_network-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 7, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page