Skip to main content

lughus logo

PyPI version Supported Python versions License: MIT

lughus

Micro-framework for building A2A agents with LiteLLM. Register tools, run an agentic loop, get a result. No graphs, no runners, no magic.

Install

pip install lughus              # Core (litellm, orjson, jsonschema)
pip install lughus[server]      # + FastAPI, uvicorn, a2a-sdk
pip install lughus[all]         # Everything

Quick Start

A complete agent in one script. Register a tool, call agent_loop, get the LLM's response:

import asyncio
import json

from lughus import ToolRegistry, agent_loop
from lughus.testing import MockLLM


# 1. Create a tool registry and register a tool
registry = ToolRegistry()


@registry.tool(
    "greet",
    "Greet a user by name.",
    {
        "type": "object",
        "properties": {
            "name": {"type": "string", "description": "Name to greet"},
        },
        "required": ["name"],
        "additionalProperties": False,
    },
)
def greet(*, name: str, state) -> str:
    return json.dumps({"greeting": f"Hello, {name}!"})


# 2. Create an LLM (MockLLM for offline testing, LLM for production)
llm = MockLLM(
    [
        # Turn 1: LLM calls the greet tool
        [{"name": "greet", "arguments": {"name": "World"}, "id": "call_1"}],
        # Turn 2: LLM produces a text response (ends the loop)
        "Hello, World!",
    ]
)


# 3. Run the agent loop
async def main():
    result = await agent_loop(
        llm,
        system="You are a greeting assistant. Use the greet tool.",
        context="Say hello to World",
        registry=registry,
        tool_names=["greet"],
        state=None,
    )
    print(result)  # "Hello, World!"
    print(f"{result.iterations} iterations, {result.total_tokens} tokens")


asyncio.run(main())

For production, swap MockLLM for a real LLM:

from lughus import LLM

llm = LLM(model="openai/gpt-4o", max_output_tokens=16384)

Features

  • agent_loop() -- iterates LLM + tools until a text response, with parallel tool execution
  • agent_loop_stream() -- same, but yields text chunks as the LLM generates them
  • ToolRegistry -- @registry.tool() decorator for sync and async Python functions
  • BaseGateway -- A2A AgentExecutor (message extraction, artifact handling)
  • LLM -- thin wrapper around litellm.acompletion(), supports 100+ providers
  • build_app() / serve() -- A2A ASGI app + uvicorn in one call
  • Governance -- deterministic tool policies, scoped permissions, human-in-the-loop approvals
  • Observability -- native OpenTelemetry traces and metrics on every request

Configuration

All configuration is via environment variables. Key settings:

Variable Default Description
AGENT_MODEL (required) LiteLLM model string (e.g. openai/gpt-4o)
MAX_OUTPUT_TOKENS 16384 Max output tokens per LLM call
HOST / PORT 0.0.0.0 / 8080 Server listen address
LUGHUS_ENV development Set production for strict startup validation
API_BEARER_TOKEN (not set) Bearer token for non-health routes

Provider routing is automatic via LiteLLM:

export AGENT_MODEL="openai/gpt-4o"       && export OPENAI_API_KEY="sk-..."
export AGENT_MODEL="anthropic/claude-sonnet-4-20250514" && export ANTHROPIC_API_KEY="sk-ant-..."
export AGENT_MODEL="gemini/gemini-2.5-flash" && export GEMINI_API_KEY="..."

Scaffold a New Agent

lughus new my_agent
cd my_agent && pip install -e ".[dev]" && pytest -q
python -m my_agent  # starts A2A server on :8080

Governance

Tools can declare risk levels, required scopes, and approval workflows. The policy engine evaluates actions deterministically before execution -- prompt instructions are never used as access controls. See docs/guides/agentic-design.md for agentic design rules.

from lughus import ToolRegistry, ToolRisk, ToolEffect

registry = ToolRegistry()

@registry.tool(
    "deploy",
    "Deploy to production.",
    {"type": "object", "properties": {"service": {"type": "string"}}, "required": ["service"]},
    risk=ToolRisk.CRITICAL,
    effects=frozenset([ToolEffect.WRITE, ToolEffect.IRREVERSIBLE]),
    requires_approval=True,
)
def deploy(*, service: str, state) -> str:
    return json.dumps({"status": "deployed"})

Links

License

MIT -- see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lughus-0.14.1.tar.gz (168.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lughus-0.14.1-py3-none-any.whl (112.6 kB view details)

Uploaded Python 3

File details

Details for the file lughus-0.14.1.tar.gz.

File metadata

  • Download URL: lughus-0.14.1.tar.gz
  • Upload date:
  • Size: 168.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for lughus-0.14.1.tar.gz
Algorithm Hash digest
SHA256 6563c5362d866518e0e86355985a5602ff2e29790e41634cf2c1af5ee9b7d2ff
MD5 92c29cc8050f77d72bfd7b17f7ec38d7
BLAKE2b-256 3be6be7628fac1458cf89d37e5cdb80eb99bd84e692cfbec1197722cc071529a

See more details on using hashes here.

Provenance

The following attestation bundles were made for lughus-0.14.1.tar.gz:

Publisher: publish.yml on hdg-zero/lughus

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file lughus-0.14.1-py3-none-any.whl.

File metadata

  • Download URL: lughus-0.14.1-py3-none-any.whl
  • Upload date:
  • Size: 112.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for lughus-0.14.1-py3-none-any.whl
Algorithm Hash digest
SHA256 53dade5498156bc84ca85fccc3debdd1eb1e0b92013f9700226e2dd2681dd965
MD5 f90ad52bf55f6a775e64655750d39066
BLAKE2b-256 4a2e54dac74c3952b318b1125cda45a7315daf08b173f8e9a36dfa09191f09e6

See more details on using hashes here.

Provenance

The following attestation bundles were made for lughus-0.14.1-py3-none-any.whl:

Publisher: publish.yml on hdg-zero/lughus

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.20.0

2 files

0.19.0

2 files

0.18.0

2 files

0.17.0

2 files

0.15.0

2 files

This release

0.14.1 This release

2 files

0.12.0

2 files

0.11.0

2 files

0.10.2

2 files

0.10.1

2 files

0.9.0

2 files

0.8.0

2 files

0.7.0

2 files

0.6.0

2 files

0.5.1

2 files

0.5.0

2 files

0.4.0

2 files

0.3.0

2 files

0.2.0

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

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