Hire Team

INDUSAGI DOCUMENTATION

indusagi (Python) Overview

Preserved documentation snapshot. APIs and capabilities differ by edition and version. Check the selected package before implementation. View pinned source.

View Python Framework source on GitHub
On this page

indusagi is a terminal-first AI coding-agent framework for Python. It ships both the pindusagi CLI and an embeddable library surface organized by capability layer, imported as import indusagi (with lazy subsystem aliases) or per-layer (import indusagi.runtime, import indusagi.llmgateway, ...).

Table of Contents

What it is

indusagi is a toolkit, not a single product. The same package gives you a runnable coding agent on the command line (pindusagi) and the building blocks to embed an agent in your own code: a multi-provider LLM gateway, a pure agent runtime, a built-in tool kernel, an MCP bridge, SaaS connectors, multi-agent swarm coordination, an agent-builder, tracing, and a Textual-based terminal UI.

Everything is async/await, fully typed, and snake_case. It requires Python 3.11 or newer. The top-level indusagi package is a thin namespace: it eagerly binds only VERSION / __version__ and lazily re-exports the subsystems on first attribute access.

Install

# core only (httpx, pydantic, wcwidth, python-ulid, regex)
pip install indusagi

# with the interactive Textual TUI and MCP server mounting
pip install "indusagi[mcp,tui]"
Extra Pulls in Enables
tui textual, pygments, markdown-it-py The interactive REPL and rendered terminal UI
mcp mcp Mounting and hosting Model Context Protocol servers
dev pytest, pytest-asyncio, respx Running the test suite from a checkout

Installing the package also provides two console scripts, indusagi and pindusagi (both map to indusagi.shell_app.cli:run). The version is declared once in pyproject.toml and read at runtime via importlib.metadata; code never hardcodes it.

Quickstart

Set the provider key for the model you intend to run, then invoke the CLI. The runner is chosen from your flags: -p for one-shot print mode, --json for the NDJSON wire protocol, and the bare invocation for the interactive TUI.

export ANTHROPIC_API_KEY="sk-..."

pindusagi --version                       # prints: indusagi 0.1.2
pindusagi -p "summarize this repo"        # one-shot print mode, then exit
pindusagi --json                          # NDJSON wire protocol over stdio
pindusagi                                 # interactive Textual TUI (needs [tui])
pindusagi auth login                      # OAuth + PKCE login

Embedding is two layers: the runtime (which owns create_agent) and the capabilities layer (which assembles a runnable tool set).

import asyncio
from indusagi.runtime import create_agent
from indusagi.capabilities import tool_box

async def main() -> None:
    agent = create_agent({
        "model": "claude-sonnet-4-5",
        "tools": tool_box("coding"),       # "read_only" | "coding" | "all"
    })
    snapshot = await agent.submit("list the TODO comments in this repo")
    print(snapshot.phase)

asyncio.run(main())

State lives under ~/.pindusagi by default; override it with the INDUSAGI_HOME environment variable. See Getting Started for the full embedding and CLI walkthrough.

What's inside

The framework is a layered stack. Each layer is a real subpackage with an explicit, frozen public surface, and each is importable on its own:

Layer Module Holds
LLM core indusagi.llmgateway Model catalog, the frozen type contract, stream/complete dispatch, connector registry. Single source of truth for gateway types.
Runtime indusagi.runtime create_agent, the RunSnapshot/RunEvent/AgentConfig vocabulary, and the pure cadence/step transition machine.
Tools indusagi.capabilities The define_tool kernel, the built-in tool objects (read/write/edit/ls/grep/find/bash/process/todo/web), local backends, and tool_box.
MCP bridge indusagi.interop Server endpoints and fleets (client side) plus a provider host, contract types, and ProtocolFault.
Connectors indusagi.connectors The SaasGateway façade, the SaasBackend port, the Composio adapter, and the fluent ScopePlanner.
Swarm indusagi.swarm create_crew/Crew and roster / workboard / mailbox / git-worktree isolation / telemetry services.
Smithy indusagi.smithy The agent-builder meta-tool: FlagReader, AgentBlueprint/PROFILES, KnowledgePack, and the Forge build session.
Tracing indusagi.tracing A homegrown, OTel-free tracer: signal / channel / redaction / sinks / recorder / registry / adapter.
CLI indusagi.shell_app The application: main/run, the runner registry, invocation parser, settings, upgrades, and auth.
UI indusagi.tui / react_ink / ui_bridge / react_host TUI primitives (textual-free), the Textual component library, the on-screen bridge, and the backend Protocol seam.

Three facades preserve the original TypeScript vocabulary as thin shims over the core for migrating code: indusagi.ai (over llmgateway), indusagi.agent (over runtime + capabilities), and indusagi.mcp (over interop, keeping camelCase names). indusagi.memory is an intentional empty stub for layout parity — real conversational memory lives in indusagi.runtime.

The import surface

The root package binds only the version eagerly; every subsystem resolves lazily so importing indusagi never drags in textual or mcp.

Name Kind Source Purpose
VERSION / __version__ const __init__.py Read from importlib.metadata; falls back to "0.0.0.dev0" in an uninstalled source tree. The only eager exports.
__getattr__ function __init__.py PEP-562 lazy alias resolution: imports the target subpackage on first access.

The lazy aliases mirror the layered map (a few use friendlier names than the underlying module):

import indusagi

print(indusagi.VERSION)        # "0.1.2" (or "0.0.0.dev0" from a source tree)

gateway = indusagi.gateway     # -> indusagi.llmgateway
saas    = indusagi.saas        # -> indusagi.connectors
shell   = indusagi.shell       # -> indusagi.shell_app
print(gateway.__name__)        # 'indusagi.llmgateway'

# NOTE: `from indusagi import stream` FAILS — the root exports only VERSION /
# __version__. Import from the subpackage instead: from indusagi.llmgateway import stream

Full alias table and per-layer __all__ lists: Package Exports.

Models and providers

The gateway routes 841 models across 24 providers out of a single catalog. Resolve a model id to a card, query the catalog fluently, and estimate cost — all without a network call:

from indusagi.llmgateway import models, get_card, estimate_cost

card = get_card("claude-sonnet-4-5")          # context window / pricing / wire dialect
if card:
    cost = estimate_cost(card, {"input_tokens": 1000, "output_tokens": 500})

for c in models():                            # fluent query over the catalog
    ...

Dispatch (stream / complete) takes a model id, a Conversation, and optional StreamOptions; unknown ids fail fast with an unsupported GatewayError. See the LLM Gateway for the contract and connector details.

Where to next