pip install hanzo shipped a 10-command CLI, not the 56-command one
`hanzo` depends on `hanzo-cli`, and BOTH declared `[project.scripts] hanzo`. Entry-point resolution is install-order dependent, so which CLI a user got was a coin flip — and hanzo-cli kept winning. The result: $ hanzo auth login Error: No such command 'auth'. So the "auth login is broken by Cloudflare 1010" story was real but unreachable: users never got as far as the HTTP call, because the binary they had did not have an `auth` command at all. Publishing that fix would have changed nothing. One command, one owner: - hanzo-cli drops its console script. `hanzo` is the ONE command. - `paas` and `bot` are mounted into it — the only two groups with no equivalent. `kms` is NOT mounted: `hanzo secrets` is a strict superset (audit/grant/ revoke/rollback/rotate/versions on top of the same get/list/set/delete), and two commands for one concern is what we are removing. - hanzo_cli grows a __main__ so it stays invocable as `python -m hanzo_cli`, and its e2e suite targets that instead of whatever `hanzo` resolves to. Endpoints, one definition: - models.IAMConfig (the class the package EXPORTS) gains the HIP-0111 endpoint properties. config.IAMConfig had them, but nothing imports that one — a second same-named class nobody uses is how the legacy path survived. - config.py + fastapi.py stop hand-assembling paths and read the constants. - password_login posted to `/oauth/token`, which is not a 404: IAM serves a 200 text/html SPA catch-all for unregistered paths, so it received a login PAGE and json() blew up on HTML. Verified: legacy 200 text/html vs canonical 401 application/json. PKCE, because this is a public client: - browser_login ships no client_secret, so the authorization code was the only secret in the flow and it arrives over a plaintext loopback redirect. The SDK already accepted code_challenge/code_verifier; the CLI simply never passed them. RFC 8252 §8.1 / RFC 7636 S256. Version, one source: - pyproject said 0.4.4, __init__ said 0.3.47, cli.py said 0.3.48, and the installed binary reported 0.1.0 — four answers, none right. Now resolved from the installed distribution. Verified on a clean venv: entry-point providers 2 -> 1, commands 10 -> 58, `hanzo --version` 0.1.0 -> 0.4.4, all four endpoints canonical. hanzo-iam 19/19 pass; hanzo-cli's 20 failures are unchanged before and after and are all live-service auth (no stored token in this environment). Co-authored-by: Hanzo Dev <[email protected]>
Hanzo Python SDK
The flagship Python SDK for the Open AI Cloud — models, agents, tools, memory, and MCP in one install.
This is the most complete Hanzo SDK — a uv workspace of 60+ composable packages
covering the full AI surface: the typed cloud client, an agent framework, the
Model Context Protocol server and tools, persistent memory + RAG, distributed
compute, and a batteries-included CLI. If you build AI in Python, start here.
Install
pip install hanzo # flagship: CLI + agents + MCP + client
Or install exactly what you need:
pip install hanzoai # just the typed cloud API client
pip install "hanzo[all]" # everything, including optional extras
Quickstart
from hanzoai import ApiClient, Configuration, AiOpenAICompatibleApi
from hanzoai import AiChatCompletionRequest, AiChatMessage
config = Configuration(host="https://api.hanzo.ai", access_token="sk-...")
with ApiClient(config) as client:
ai = AiOpenAICompatibleApi(client)
resp = ai.ai_create_chat_completion(
AiChatCompletionRequest(
model="zen-coder",
messages=[AiChatMessage(role="user", content="Ship it.")],
)
)
print(resp.choices[0].message.content)
Every route is https://api.hanzo.ai/v1/<service>/*. Models come from the Zen
family (our own models) plus any provider you connect — one typed client, no proxy
in the middle.
Packages
The workspace splits cleanly by concern. The headline packages:
| Package | Purpose |
|---|---|
hanzoai |
Typed cloud API client (generated from the Hanzo OpenAPI surface). |
hanzo |
The hanzo CLI + runtime that ties everything together. |
hanzo-mcp |
Model Context Protocol server — discovers tools via entry points. |
hanzo-agents / hanzo-agent |
Agent framework — build and orchestrate agents and swarms. |
hanzo-network |
Distributed AI compute and node orchestration. |
hanzo-memory |
Persistent memory + RAG (SQLite, optional vector backends). |
hanzo-tools-* |
60+ single-concern tool packages (shell, browser, fs, code, vector, iam, …), each exposing a TOOLS list. |
python-sdk/
└── pkg/
├── hanzoai/ # typed cloud client (OpenAPI-generated)
├── hanzo/ # CLI + runtime meta package
├── hanzo-mcp/ # MCP server (entry-point tool discovery)
├── hanzo-agents/ # agent framework
├── hanzo-network/ # distributed compute
├── hanzo-memory/ # memory + RAG
└── hanzo-tools-*/ # composable tool packages
CLI
pip install hanzo gives you the hanzo command:
hanzo chat # chat with the Zen models
hanzo node # start / manage a local compute node
hanzo mcp # run the MCP server for your editor or agent
hanzo agent # build and run agents
hanzo run # run a workflow
hanzo cloud # manage cloud resources
hanzo search # AI-powered search
Run hanzo --help for the full command tree.
Model Context Protocol (hanzo-mcp)
hanzo-mcp hosts the MCP server and discovers tools through
[project.entry-points."hanzo.tools"], so any installed hanzo-tools-* package
lights up automatically.
from hanzo_mcp import create_mcp_server
server = create_mcp_server()
server.register_tool(my_tool)
server.start()
Agents (hanzo-agents)
from hanzo_agents import Agent, Swarm
agent = Agent(
name="researcher",
model="zen-coder",
instructions="You are a research assistant.",
)
swarm = Swarm([agent])
result = await swarm.run("Research quantum computing.")
Network (hanzo-network)
from hanzo_network import LocalComputeNode, DistributedNetwork
node = LocalComputeNode(node_id="node-001")
network = DistributedNetwork()
network.register_node(node)
Memory (hanzo-memory)
Persistent memory and RAG backed by SQLite, with optional vector search
(sqlite-vec, lancedb, kuzu). Global state lives in ~/.hanzo/; per-project
state in .hanzo/.
from hanzo_memory import MemoryService
memory = MemoryService()
await memory.store("key", "value")
result = await memory.retrieve("key")
Development
This is a uv workspace.
git clone https://github.com/hanzoai/python-sdk.git
cd python-sdk
uv sync --all-packages # install the whole workspace
uv run pytest tests/ -v # run tests
make lint # ruff lint
make format # ruff format
make type-check # mypy / pyright
Per-package work:
uv run pytest pkg/hanzo-mcp -v
cd pkg/hanzo && uv build
Configuration
HANZO_API_KEY=your-api-key
HANZO_BASE_URL=https://api.hanzo.ai
HANZO_LOG_LEVEL=INFO
Or ~/.hanzo/config.yaml:
api:
key: your-api-key
base_url: https://api.hanzo.ai
logging:
level: INFO
Security
- Transport is TLS 1.3+. Secrets belong in a KMS, never in source or plaintext.
- SOC 2 audit in progress; HIPAA BAA available.
Report vulnerabilities to [email protected]. See SECURITY.md.
Contributing
Contributions welcome — see CONTRIBUTING.md. Use type hints,
add tests for new behavior, and run make lint before opening a PR.
License
Apache License 2.0 — see LICENSE.
Support
- Docs: docs.hanzo.ai
- Issues: github.com/hanzoai/python-sdk/issues
- Email: [email protected]
Hanzo — the Open AI Cloud
Open source · every language · on-chain settlement. hanzo.ai · docs.hanzo.ai
SDKs in every language — Python (flagship) · TypeScript · Go · Rust · C++ · Swift · Kotlin · umbrella