hanzo 0.3.6__py3-none-any.whl → 0.3.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of hanzo might be problematic. Click here for more details.

hanzo/repl.py CHANGED
@@ -1,6 +1,7 @@
1
1
  """REPL and AI chat entry points for Hanzo."""
2
2
 
3
3
  import sys
4
+
4
5
  import click
5
6
 
6
7
 
@@ -9,11 +10,15 @@ def ai_chat():
9
10
  try:
10
11
  # Use hanzo-router instead of litellm for AI routing
11
12
  from hanzo_repl.cli import main as repl_main
13
+
12
14
  # Pass AI chat mode
13
15
  sys.argv = [sys.argv[0], "--mode", "ai"]
14
16
  repl_main()
15
17
  except ImportError:
16
- click.echo("Error: hanzo-repl or hanzo-router is not installed. Please run: pip install hanzo[ai] or pip install hanzo[all]", err=True)
18
+ click.echo(
19
+ "Error: hanzo-repl or hanzo-router is not installed. Please run: pip install hanzo[ai] or pip install hanzo[all]",
20
+ err=True,
21
+ )
17
22
  sys.exit(1)
18
23
 
19
24
 
@@ -21,15 +26,20 @@ def repl_main():
21
26
  """Start the Hanzo REPL interface (hanzo/repl)."""
22
27
  try:
23
28
  from hanzo_repl.cli import main as repl_cli_main
29
+
24
30
  repl_cli_main()
25
31
  except ImportError:
26
- click.echo("Error: hanzo-repl is not installed. Please run: pip install hanzo[all]", err=True)
32
+ click.echo(
33
+ "Error: hanzo-repl is not installed. Please run: pip install hanzo[all]",
34
+ err=True,
35
+ )
27
36
  sys.exit(1)
28
37
 
29
38
 
30
39
  if __name__ == "__main__":
31
40
  import os
41
+
32
42
  if os.path.basename(sys.argv[0]) in ["ai", "chat"]:
33
43
  ai_chat()
34
44
  else:
35
- repl_main()
45
+ repl_main()
hanzo/router/__init__.py CHANGED
@@ -3,25 +3,37 @@
3
3
  try:
4
4
  # Import directly from the installed router package
5
5
  import router
6
- from router import Router, completion, acompletion, embedding, aembedding
7
-
6
+ from router import Router, embedding, aembedding, completion, acompletion
7
+
8
8
  # Re-export the entire router module
9
- __all__ = ["router", "Router", "completion", "acompletion", "embedding", "aembedding"]
10
-
9
+ __all__ = [
10
+ "router",
11
+ "Router",
12
+ "completion",
13
+ "acompletion",
14
+ "embedding",
15
+ "aembedding",
16
+ ]
17
+
11
18
  # Make router available as a submodule
12
19
  import sys
13
- sys.modules['hanzo.router'] = router
14
-
20
+
21
+ sys.modules["hanzo.router"] = router
22
+
15
23
  except ImportError as e:
16
24
  # If router is not installed, provide helpful error
17
25
  import sys
26
+
18
27
  print(f"Error importing router: {e}", file=sys.stderr)
19
- print("Please install router from the main repository: pip install -e /Users/z/work/hanzo/router", file=sys.stderr)
20
-
28
+ print(
29
+ "Please install router from the main repository: pip install -e /Users/z/work/hanzo/router",
30
+ file=sys.stderr,
31
+ )
32
+
21
33
  # Define placeholders to avoid complete failure
22
34
  router = None
23
35
  Router = None
24
36
  completion = None
25
37
  acompletion = None
26
38
  embedding = None
27
- aembedding = None
39
+ aembedding = None
hanzo/utils/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  """Utility modules for Hanzo CLI."""
2
2
 
3
- __all__ = ["config", "output"]
3
+ __all__ = ["config", "output"]
hanzo/utils/config.py CHANGED
@@ -1,9 +1,9 @@
1
1
  """Configuration utilities for Hanzo CLI."""
2
2
 
3
- import json
4
3
  import os
5
- from pathlib import Path
4
+ import json
6
5
  from typing import Any, Dict, Optional
6
+ from pathlib import Path
7
7
 
8
8
  import yaml
9
9
 
@@ -11,17 +11,21 @@ import yaml
11
11
  def get_config_paths() -> Dict[str, Path]:
12
12
  """Get configuration file paths."""
13
13
  paths = {}
14
-
14
+
15
15
  # System config
16
16
  if os.name == "nt": # Windows
17
- paths["system"] = Path(os.environ.get("PROGRAMDATA", "C:\\ProgramData")) / "hanzo" / "config.yaml"
17
+ paths["system"] = (
18
+ Path(os.environ.get("PROGRAMDATA", "C:\\ProgramData"))
19
+ / "hanzo"
20
+ / "config.yaml"
21
+ )
18
22
  else: # Unix-like
19
23
  paths["system"] = Path("/etc/hanzo/config.yaml")
20
-
24
+
21
25
  # Global config (user)
22
26
  config_home = Path(os.environ.get("XDG_CONFIG_HOME", Path.home() / ".config"))
23
27
  paths["global"] = config_home / "hanzo" / "config.yaml"
24
-
28
+
25
29
  # Local config (project)
26
30
  cwd = Path.cwd()
27
31
  for parent in [cwd] + list(cwd.parents):
@@ -32,7 +36,7 @@ def get_config_paths() -> Dict[str, Path]:
32
36
  else:
33
37
  # Default local path even if it doesn't exist
34
38
  paths["local"] = cwd / ".hanzo" / "config.yaml"
35
-
39
+
36
40
  return paths
37
41
 
38
42
 
@@ -40,7 +44,7 @@ def load_config(path: Path) -> Dict[str, Any]:
40
44
  """Load configuration from file."""
41
45
  if not path.exists():
42
46
  return {}
43
-
47
+
44
48
  try:
45
49
  with open(path, "r") as f:
46
50
  if path.suffix == ".json":
@@ -54,7 +58,7 @@ def load_config(path: Path) -> Dict[str, Any]:
54
58
  def save_config(path: Path, config: Dict[str, Any]):
55
59
  """Save configuration to file."""
56
60
  path.parent.mkdir(parents=True, exist_ok=True)
57
-
61
+
58
62
  with open(path, "w") as f:
59
63
  if path.suffix == ".json":
60
64
  json.dump(config, f, indent=2)
@@ -65,31 +69,31 @@ def save_config(path: Path, config: Dict[str, Any]):
65
69
  def get_config_value(key: str, default: Any = None, scope: Optional[str] = None) -> Any:
66
70
  """Get configuration value from merged configs."""
67
71
  paths = get_config_paths()
68
-
72
+
69
73
  # Load configs in priority order (local > global > system)
70
74
  configs = []
71
-
75
+
72
76
  if scope == "system" or scope is None:
73
77
  if paths["system"].exists():
74
78
  configs.append(load_config(paths["system"]))
75
-
79
+
76
80
  if scope == "global" or scope is None:
77
81
  if paths["global"].exists():
78
82
  configs.append(load_config(paths["global"]))
79
-
83
+
80
84
  if scope == "local" or scope is None:
81
85
  if paths.get("local") and paths["local"].exists():
82
86
  configs.append(load_config(paths["local"]))
83
-
87
+
84
88
  # Merge configs (later ones override earlier)
85
89
  merged = {}
86
90
  for config in configs:
87
91
  merged.update(config)
88
-
92
+
89
93
  # Get nested key
90
94
  keys = key.split(".")
91
95
  current = merged
92
-
96
+
93
97
  try:
94
98
  for k in keys:
95
99
  current = current[k]
@@ -102,49 +106,45 @@ def set_config_value(key: str, value: Any, scope: str = "global"):
102
106
  """Set configuration value."""
103
107
  paths = get_config_paths()
104
108
  path = paths.get(scope, paths["global"])
105
-
109
+
106
110
  config = load_config(path) if path.exists() else {}
107
-
111
+
108
112
  # Set nested key
109
113
  keys = key.split(".")
110
114
  current = config
111
-
115
+
112
116
  for k in keys[:-1]:
113
117
  if k not in current:
114
118
  current[k] = {}
115
119
  current = current[k]
116
-
120
+
117
121
  current[keys[-1]] = value
118
-
122
+
119
123
  save_config(path, config)
120
124
 
121
125
 
122
126
  def init_config() -> Dict[str, Path]:
123
127
  """Initialize configuration structure."""
124
128
  paths = get_config_paths()
125
-
129
+
126
130
  # Create global config if it doesn't exist
127
131
  if not paths["global"].exists():
128
132
  default_config = {
129
133
  "default_model": "llama-3.2-3b",
130
134
  "default_provider": "local",
131
- "mcp": {
132
- "allowed_paths": [str(Path.home())],
133
- "enable_all_tools": True
134
- },
135
- "cluster": {
136
- "default_name": "hanzo-local",
137
- "default_port": 8000
138
- }
135
+ "mcp": {"allowed_paths": [str(Path.home())], "enable_all_tools": True},
136
+ "cluster": {"default_name": "hanzo-local", "default_port": 8000},
139
137
  }
140
138
  save_config(paths["global"], default_config)
141
-
139
+
142
140
  return paths
143
141
 
144
142
 
145
143
  def get_default_model() -> str:
146
144
  """Get default model from config or environment."""
147
- return os.environ.get("HANZO_DEFAULT_MODEL") or get_config_value("default_model", "llama-3.2-3b")
145
+ return os.environ.get("HANZO_DEFAULT_MODEL") or get_config_value(
146
+ "default_model", "llama-3.2-3b"
147
+ )
148
148
 
149
149
 
150
150
  def get_api_key(provider: str) -> Optional[str]:
@@ -156,15 +156,17 @@ def get_api_key(provider: str) -> Optional[str]:
156
156
  "hanzo": "HANZO_API_KEY",
157
157
  "groq": "GROQ_API_KEY",
158
158
  }
159
-
159
+
160
160
  if env_key := env_map.get(provider.lower()):
161
161
  if key := os.environ.get(env_key):
162
162
  return key
163
-
163
+
164
164
  # Check config
165
165
  return get_config_value(f"api_keys.{provider}")
166
166
 
167
167
 
168
168
  def is_local_preferred() -> bool:
169
169
  """Check if local execution is preferred."""
170
- return os.environ.get("HANZO_USE_LOCAL", "").lower() == "true" or get_config_value("prefer_local", False)
170
+ return os.environ.get("HANZO_USE_LOCAL", "").lower() == "true" or get_config_value(
171
+ "prefer_local", False
172
+ )
hanzo/utils/net_check.py CHANGED
@@ -1,33 +1,33 @@
1
1
  """Utilities for checking hanzo/net availability and dependencies."""
2
2
 
3
- import os
4
- import subprocess
5
3
  import sys
6
- from typing import Optional, Tuple
4
+ import subprocess
5
+ from typing import Tuple, Optional
7
6
  from pathlib import Path
8
7
 
9
8
 
10
9
  def check_net_installation() -> Tuple[bool, Optional[str], Optional[str]]:
11
10
  """Check if hanzo/net is available and properly configured.
12
-
11
+
13
12
  Returns:
14
13
  Tuple of (is_available, net_path, python_exe)
15
14
  """
16
15
  # First try to import as PyPI package (hanzo-net)
17
16
  try:
18
17
  import net
18
+
19
19
  return True, None, sys.executable
20
20
  except ImportError:
21
21
  pass
22
-
22
+
23
23
  # For development: check for hanzo/net in standard location
24
24
  net_path = Path.home() / "work" / "hanzo" / "net"
25
25
  if not net_path.exists():
26
26
  net_path = Path("/Users/z/work/hanzo/net")
27
-
27
+
28
28
  if not net_path.exists():
29
29
  return False, None, None
30
-
30
+
31
31
  # Check for venv
32
32
  venv_python = net_path / ".venv" / "bin" / "python"
33
33
  if venv_python.exists():
@@ -35,21 +35,19 @@ def check_net_installation() -> Tuple[bool, Optional[str], Optional[str]]:
35
35
  result = subprocess.run(
36
36
  [str(venv_python), "-c", "import net, scapy, mlx, transformers"],
37
37
  capture_output=True,
38
- text=True
38
+ text=True,
39
39
  )
40
40
  if result.returncode == 0:
41
41
  return True, str(net_path), str(venv_python)
42
42
  else:
43
43
  # Venv exists but missing dependencies
44
44
  return False, str(net_path), str(venv_python)
45
-
45
+
46
46
  # No venv, check system Python
47
47
  result = subprocess.run(
48
- [sys.executable, "-c", "import scapy"],
49
- capture_output=True,
50
- text=True
48
+ [sys.executable, "-c", "import scapy"], capture_output=True, text=True
51
49
  )
52
-
50
+
53
51
  if result.returncode == 0:
54
52
  return True, str(net_path), sys.executable
55
53
  else:
@@ -58,52 +56,58 @@ def check_net_installation() -> Tuple[bool, Optional[str], Optional[str]]:
58
56
 
59
57
  def install_net_dependencies(net_path: str, python_exe: str = None) -> bool:
60
58
  """Install hanzo/net dependencies.
61
-
59
+
62
60
  Args:
63
61
  net_path: Path to hanzo/net directory
64
62
  python_exe: Python executable to use (optional)
65
-
63
+
66
64
  Returns:
67
65
  True if installation successful
68
66
  """
69
67
  if python_exe is None:
70
68
  python_exe = sys.executable
71
-
69
+
72
70
  # Install dependencies
73
71
  result = subprocess.run(
74
72
  [python_exe, "-m", "pip", "install", "-e", net_path],
75
73
  capture_output=True,
76
- text=True
74
+ text=True,
77
75
  )
78
-
76
+
79
77
  return result.returncode == 0
80
78
 
81
79
 
82
80
  def get_missing_dependencies(python_exe: str = None) -> list:
83
81
  """Check which dependencies are missing for hanzo/net.
84
-
82
+
85
83
  Args:
86
84
  python_exe: Python executable to check (default: sys.executable)
87
-
85
+
88
86
  Returns:
89
87
  List of missing package names
90
88
  """
91
89
  if python_exe is None:
92
90
  python_exe = sys.executable
93
-
91
+
94
92
  required_packages = [
95
- "scapy", "mlx", "mlx_lm", "transformers", "tinygrad",
96
- "aiohttp", "grpcio", "pydantic", "rich", "tqdm"
93
+ "scapy",
94
+ "mlx",
95
+ "mlx_lm",
96
+ "transformers",
97
+ "tinygrad",
98
+ "aiohttp",
99
+ "grpcio",
100
+ "pydantic",
101
+ "rich",
102
+ "tqdm",
97
103
  ]
98
-
104
+
99
105
  missing = []
100
106
  for package in required_packages:
101
107
  result = subprocess.run(
102
- [python_exe, "-c", f"import {package}"],
103
- capture_output=True,
104
- text=True
108
+ [python_exe, "-c", f"import {package}"], capture_output=True, text=True
105
109
  )
106
110
  if result.returncode != 0:
107
111
  missing.append(package)
108
-
109
- return missing
112
+
113
+ return missing
hanzo/utils/output.py CHANGED
@@ -1,20 +1,22 @@
1
1
  """Output utilities for Hanzo CLI."""
2
2
 
3
- from functools import wraps
4
3
  from typing import Any, Callable
4
+ from functools import wraps
5
5
 
6
- from rich.console import Console
7
6
  from rich.theme import Theme
7
+ from rich.console import Console
8
8
 
9
9
  # Custom theme
10
- hanzo_theme = Theme({
11
- "info": "cyan",
12
- "warning": "yellow",
13
- "error": "red",
14
- "success": "green",
15
- "dim": "dim white",
16
- "highlight": "bold cyan",
17
- })
10
+ hanzo_theme = Theme(
11
+ {
12
+ "info": "cyan",
13
+ "warning": "yellow",
14
+ "error": "red",
15
+ "success": "green",
16
+ "dim": "dim white",
17
+ "highlight": "bold cyan",
18
+ }
19
+ )
18
20
 
19
21
  # Global console instance
20
22
  console = Console(theme=hanzo_theme)
@@ -22,6 +24,7 @@ console = Console(theme=hanzo_theme)
22
24
 
23
25
  def handle_errors(func: Callable) -> Callable:
24
26
  """Decorator to handle errors in CLI commands."""
27
+
25
28
  @wraps(func)
26
29
  async def async_wrapper(*args, **kwargs):
27
30
  try:
@@ -32,7 +35,7 @@ def handle_errors(func: Callable) -> Callable:
32
35
  console.print(f"[error]Error: {e}[/error]")
33
36
  if console.is_debug:
34
37
  console.print_exception()
35
-
38
+
36
39
  @wraps(func)
37
40
  def sync_wrapper(*args, **kwargs):
38
41
  try:
@@ -43,7 +46,7 @@ def handle_errors(func: Callable) -> Callable:
43
46
  console.print(f"[error]Error: {e}[/error]")
44
47
  if console.is_debug:
45
48
  console.print_exception()
46
-
49
+
47
50
  if asyncio.iscoroutinefunction(func):
48
51
  return async_wrapper
49
52
  return sync_wrapper
@@ -59,31 +62,33 @@ def print_table(data: list[dict], title: str = None):
59
62
  if not data:
60
63
  console.print("[dim]No data[/dim]")
61
64
  return
62
-
65
+
63
66
  from rich.table import Table
64
-
67
+
65
68
  table = Table(title=title)
66
-
69
+
67
70
  # Add columns from first row
68
71
  for key in data[0].keys():
69
72
  table.add_column(key.replace("_", " ").title())
70
-
73
+
71
74
  # Add rows
72
75
  for row in data:
73
76
  table.add_row(*[str(v) for v in row.values()])
74
-
77
+
75
78
  console.print(table)
76
79
 
77
80
 
78
81
  def confirm(message: str, default: bool = False) -> bool:
79
82
  """Ask for confirmation."""
80
83
  from rich.prompt import Confirm
84
+
81
85
  return Confirm.ask(message, default=default)
82
86
 
83
87
 
84
88
  def prompt(message: str, default: str = None, password: bool = False) -> str:
85
89
  """Prompt for input."""
86
90
  from rich.prompt import Prompt
91
+
87
92
  return Prompt.ask(message, default=default, password=password)
88
93
 
89
94
 
@@ -100,4 +105,4 @@ clear = console.clear
100
105
 
101
106
 
102
107
  # Import asyncio for the decorator
103
- import asyncio
108
+ import asyncio
@@ -0,0 +1,138 @@
1
+ Metadata-Version: 2.4
2
+ Name: hanzo
3
+ Version: 0.3.7
4
+ Summary: Hanzo AI - Complete AI Infrastructure Platform with CLI, Router, MCP, and Agent Runtime
5
+ Project-URL: Homepage, https://hanzo.ai
6
+ Project-URL: Repository, https://github.com/hanzoai/python-sdk
7
+ Project-URL: Documentation, https://docs.hanzo.ai/cli
8
+ Project-URL: Bug Tracker, https://github.com/hanzoai/python-sdk/issues
9
+ Author-email: Hanzo AI <dev@hanzo.ai>
10
+ Keywords: agents,ai,cli,hanzo,llm,local-ai,mcp,private-ai
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: Apache Software License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.8
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Requires-Python: >=3.8
25
+ Requires-Dist: click>=8.1.0
26
+ Requires-Dist: hanzo-net>=0.1.12
27
+ Requires-Dist: httpx>=0.23.0
28
+ Requires-Dist: prompt-toolkit>=3.0.0
29
+ Requires-Dist: pydantic>=2.0.0
30
+ Requires-Dist: pyyaml>=6.0
31
+ Requires-Dist: rich>=13.0.0
32
+ Requires-Dist: typer>=0.9.0
33
+ Provides-Extra: agents
34
+ Requires-Dist: hanzo-agents>=0.1.0; extra == 'agents'
35
+ Requires-Dist: hanzo-network>=0.1.2; extra == 'agents'
36
+ Provides-Extra: ai
37
+ Requires-Dist: hanzoai>=1.0.0; extra == 'ai'
38
+ Provides-Extra: all
39
+ Requires-Dist: hanzo-aci>=0.2.8; extra == 'all'
40
+ Requires-Dist: hanzo-agents>=0.1.0; extra == 'all'
41
+ Requires-Dist: hanzo-mcp>=0.7.0; extra == 'all'
42
+ Requires-Dist: hanzo-memory>=1.0.0; extra == 'all'
43
+ Requires-Dist: hanzo-network>=0.1.2; extra == 'all'
44
+ Requires-Dist: hanzo-repl>=0.1.0; extra == 'all'
45
+ Requires-Dist: hanzoai>=1.0.0; extra == 'all'
46
+ Provides-Extra: dev
47
+ Requires-Dist: hanzo-aci>=0.2.8; extra == 'dev'
48
+ Provides-Extra: mcp
49
+ Requires-Dist: hanzo-mcp>=0.7.0; extra == 'mcp'
50
+ Provides-Extra: repl
51
+ Requires-Dist: hanzo-repl>=0.1.0; extra == 'repl'
52
+ Provides-Extra: router
53
+ Description-Content-Type: text/markdown
54
+
55
+ # Hanzo AI - Complete AI Infrastructure Platform
56
+
57
+ The main SDK for the Hanzo AI ecosystem, providing unified access to all Hanzo tools and services.
58
+
59
+ ## Installation
60
+
61
+ ```bash
62
+ # Install base package with CLI
63
+ pip install hanzo
64
+
65
+ # Install with all components
66
+ pip install hanzo[all]
67
+
68
+ # Install specific components
69
+ pip install hanzo[ai] # AI SDK (same as standalone hanzoai package)
70
+ pip install hanzo[router] # LLM gateway router (replaces litellm)
71
+ pip install hanzo[mcp] # Model Context Protocol server
72
+ pip install hanzo[agents] # Agent runtime and orchestration
73
+ pip install hanzo[repl] # Interactive REPL with AI chat
74
+ ```
75
+
76
+ ## Features
77
+
78
+ - **Unified LLM Gateway**: Use `hanzo.router` instead of litellm for 100+ LLM providers
79
+ - **MCP Integration**: Full Model Context Protocol support for AI tools
80
+ - **Agent Runtime**: Build and deploy AI agents with the agent framework
81
+ - **Interactive REPL**: Chat with AI models directly from the command line
82
+ - **Complete SDK**: Import all Hanzo components from a single package
83
+
84
+ ## Quick Start
85
+
86
+ ### Command Line
87
+ ```bash
88
+ # Main CLI
89
+ hanzo --help
90
+
91
+ # Start MCP server
92
+ hanzo-mcp
93
+
94
+ # Interactive AI chat
95
+ hanzo-ai
96
+ hanzo-chat
97
+
98
+ # REPL interface
99
+ hanzo-repl
100
+ ```
101
+
102
+ ### Python SDK
103
+ ```python
104
+ import hanzo
105
+
106
+ # Use router for LLM calls (replaces litellm)
107
+ from hanzo import router
108
+ response = router.completion(
109
+ model="gpt-4",
110
+ messages=[{"role": "user", "content": "Hello!"}]
111
+ )
112
+
113
+ # Use agents
114
+ from hanzo import Agent, Network
115
+ agent = Agent(name="assistant")
116
+
117
+ # Use MCP tools
118
+ from hanzo import Tool, MCPServer
119
+
120
+ # Access AI SDK
121
+ from hanzo import Client
122
+ client = Client(api_key="...")
123
+ ```
124
+
125
+ ## Components
126
+
127
+ - **hanzo.router**: Unified LLM gateway (replaces litellm)
128
+ - **hanzo.mcp**: Model Context Protocol server and tools
129
+ - **hanzo.agents**: Agent runtime and orchestration
130
+ - **hanzo.memory**: Memory systems for agents
131
+ - **hanzo.Client**: Main AI SDK client
132
+
133
+ ## Documentation
134
+
135
+ - [Hanzo AI Docs](https://docs.hanzo.ai)
136
+ - [Router Documentation](https://docs.hanzo.ai/router)
137
+ - [MCP Documentation](https://docs.hanzo.ai/mcp)
138
+ - [Agent Documentation](https://docs.hanzo.ai/agents)