# π§
ConnectOnion
[](https://connectonion.com)
[](https://opensource.org/licenses/MIT)
[](https://python.org)
[](https://pepy.tech/projects/connectonion)
[](https://github.com/openonion/connectonion)
[](https://github.com/openonion/connectonion/graphs/contributors)
[](https://discord.gg/4xfD9k8AUF)
[](http://docs.connectonion.com)
**A simple, elegant open-source framework for production-ready AI agents**
[π Documentation](http://docs.connectonion.com) β’ [π¬ Discord](https://discord.gg/4xfD9k8AUF) β’ [β Star Us](https://github.com/openonion/connectonion)
---
> ## π Philosophy: "Keep simple things simple, make complicated things possible"
>
> This is the core principle that drives every design decision in ConnectOnion.
## π― Living Our Philosophy
### Step 1: Simple - Create and Use
```python
from connectonion import Agent
agent = Agent(name="assistant")
agent.input("Hello!") # That's it!
```
### Step 2: Add Your Tools
```python
def search(query: str) -> str:
"""Search for information."""
return f"Results for {query}"
agent = Agent(name="assistant", tools=[search])
agent.input("Search for Python tutorials")
```
### Step 3: Debug Your Agent
```python
agent = Agent(name="assistant", tools=[search])
agent.auto_debug() # Interactive debugging session
```
### Step 4: Production Ready
```python
agent = Agent(
name="production",
model="gpt-5", # Latest models
tools=[search, analyze, execute], # Your functions as tools
system_prompt=company_prompt, # Custom behavior
max_iterations=10, # Safety controls
trust="prompt" # Multi-agent ready
)
agent.input("Complex production task")
```
### Step 5: Multi-Agent - Make it Remotely Callable
```python
from connectonion import host
host(agent) # HTTP server + P2P relay - other agents can now discover and call this agent
```
## β¨ Why ConnectOnion?
Most frameworks give you a way to call LLMs. ConnectOnion gives you everything around it β so you only write prompt and tools.
### Built-in AI Programmer
```bash
co ai # Opens a chat interface with an AI that deeply understands ConnectOnion
```
`co ai` is an AI coding assistant built *with* ConnectOnion. It writes working agent code because it knows the framework inside out. Fully open-source β inspect it, modify it, build your own.
### Built-in Frontend & Backend β Just Write Prompt and Tools
Traditional path: write agent logic β build FastAPI backend β build React frontend β wire APIs β deploy.
ConnectOnion path: **write prompt and tools β deploy.**
- Backend: framework handles the API layer
- Frontend: [chat.openonion.ai](https://chat.openonion.ai) β ready-to-use chat interface
- All open-source, customizable, but you don't start from zero
### Ready-to-Use Tool Ecosystem
Import and use β no schema writing, no interface wiring:
```python
from connectonion import bash, Shell # Command execution
from connectonion.useful_tools import FileTools # File system (with safety tracking)
from connectonion.useful_tools.browser_tools import BrowserAutomation # Natural language browser automation
from connectonion import Gmail, Outlook # Email
from connectonion import GoogleCalendar # Calendar
from connectonion import Memory # Persistent memory
from connectonion import TodoList # Task tracking
```
Need to customize? Copy the source into your project:
```bash
co copy Gmail # Copies Gmail tool source code to your project for modification
```
### Built-in Approval System
Dangerous operations (bash commands, file deletion) automatically trigger approval β no permission logic needed from you.
```python
from connectonion.useful_plugins import tool_approval, shell_approval
agent = Agent("assistant", tools=[bash], plugins=[shell_approval])
# Shell commands now require approval before execution
```
Plugin-based: turn it off, customize it, or replace it entirely.
### Skills System β Auto-Discovery, Claude Code Compatible
Reusable workflows with automatic permission scoping:
```python
from connectonion.useful_plugins import skills
agent = Agent("assistant", tools=[file_tools], plugins=[skills])
# User types /commit β skill loads β git commands auto-approved β permission cleared after execution
```
Three-level auto-discovery (project β user β built-in):
```
.co/skills/skill-name/SKILL.md # Project-level (highest priority)
~/.co/skills/skill-name/SKILL.md # User-level
builtin/skill-name/SKILL.md # Built-in
```
Automatically loads Claude Code skills from `.claude/skills/` β no conversion needed.
### 12 Lifecycle Hooks + Plugin System
Inject logic at any point in the agent execution cycle:
```python
from connectonion import Agent, after_tools, llm_do
from connectonion.useful_plugins import re_act, eval, auto_compact, subagents, ulw
# Built-in plugins β same capabilities as Claude Code, open to any agent
agent = Agent("researcher", tools=[search], plugins=[
re_act, # Reflect + plan after each tool call
auto_compact, # Auto-compress context at 90% capacity
subagents, # Spawn sub-agents with independent tools and prompts
ulw, # Ultra Light Work β fully autonomous mode
])
```
These plugins mirror Claude Code's internal capabilities β `auto_compact`, `subagents`, `ulw` directly correspond to Claude Code's context compression, sub-agent spawning, and autonomous work mode. ConnectOnion makes these capabilities available to any agent you build.
Hooks: `after_user_input`, `before_iteration`, `before_llm`, `after_llm`, `before_tools`, `before_each_tool`, `after_each_tool`, `after_tools`, `on_error`, `after_iteration`, `on_stop_signal`, `on_complete`
Plugins are just lists of event handlers β visible, modifiable, `co copy`-able.
### Multi-Agent Trust System (Fast Rules)
When agents call each other, trust decisions happen **before LLM involvement** β zero token cost for 90% of cases:
```python
agent = Agent(
name="production",
trust="careful" # whitelist β allow, unknown β ask LLM, blocked β deny
)
```
Three presets: `open` (dev), `careful` (staging), `strict` (production).
---
## π¬ Join the Community
[](https://discord.gg/4xfD9k8AUF)
Get help, share agents, and discuss with 1000+ builders in our active community.
---
## π Quick Start
### Installation
```bash
pip install connectonion
```
### Quickest Start - Use the CLI
```bash
# Create a new agent project with one command
co create my-agent
# Navigate and run
cd my-agent
python agent.py
```
*The CLI guides you through API key setup automatically. No manual `.env` editing needed!*
### Manual Usage
```python
import os
from connectonion import Agent
# Set your OpenAI API key
os.environ["OPENAI_API_KEY"] = "your-api-key-here"
# 1. Define tools as simple functions
def search(query: str) -> str:
"""Search for information."""
return f"Found information about {query}"
def calculate(expression: str) -> float:
"""Perform mathematical calculations."""
return eval(expression) # Use safely in production
# 2. Create an agent with tools and personality
agent = Agent(
name="my_assistant",
system_prompt="You are a helpful and friendly assistant.",
tools=[search, calculate]
# max_iterations=10 is the default - agent will try up to 10 tool calls per task
)
# 3. Use the agent
result = agent.input("What is 25 * 4?")
print(result) # Agent will use the calculate function
result = agent.input("Search for Python tutorials")
print(result) # Agent will use the search function
# 4. View behavior history (automatic!)
print(agent.history.summary())
```
### π Interactive Debugging with `@xray`
Debug your agents like you debug code - pause at breakpoints, inspect variables, and test edge cases:
```python
from connectonion import Agent
from connectonion.decorators import xray
# Mark tools you want to debug with @xray
@xray
def search_database(query: str) -> str:
"""Search for information."""
return f"Found 3 results for '{query}'"
@xray
def send_email(to: str, subject: str) -> str:
"""Send an email."""
return f"Email sent to {to}"
# Create agent with @xray tools
agent = Agent(
name="debug_demo",
tools=[search_database, send_email]
)
# Launch interactive debugging session
agent.auto_debug()
# Or debug a specific task
agent.auto_debug("Search for Python tutorials and email the results")
```
**What happens at each `@xray` breakpoint:**
```
ββββββββββββββββββββββββββββββββββββββββββββββ
@xray BREAKPOINT: search_database
Local Variables:
query = "Python tutorials"
result = "Found 3 results for 'Python tutorials'"
What do you want to do?
β Continue execution π [c or Enter]
Edit values π [e]
Quit debugging π« [q]
π‘ Use arrow keys to navigate or type shortcuts
>
```
**Key features:**
- **Pause at breakpoints**: Tools decorated with `@xray` pause execution
- **Inspect state**: See all local variables and execution context
- **Edit variables**: Modify results to test "what if" scenarios
- **Full Python REPL**: Run any code to explore agent behavior
- **See next action**: Preview what the LLM plans to do next
Perfect for:
- Understanding why agents make certain decisions
- Testing edge cases without modifying code
- Exploring agent behavior interactively
- Debugging complex multi-tool workflows
[Learn more in the auto_debug guide](docs/auto_debug.md)
### π Plugin System
Package reusable capabilities as plugins and use them across multiple agents:
```python
from connectonion import Agent, after_tools, llm_do
# Define a reflection plugin
def add_reflection(agent):
trace = agent.current_session['trace'][-1]
if trace['type'] == 'tool_execution' and trace['status'] == 'success':
result = trace['result']
reflection = llm_do(
f"Result: {result[:200]}\n\nWhat did we learn?",
system_prompt="Be concise.",
temperature=0.3
)
agent.current_session['messages'].append({
'role': 'assistant',
'content': f"π€ {reflection}"
})
# Plugin is just a list of event handlers
reflection = [after_tools(add_reflection)] # after_tools fires once after all tools
# Use across multiple agents
researcher = Agent("researcher", tools=[search], plugins=[reflection])
analyst = Agent("analyst", tools=[analyze], plugins=[reflection])
```
**What plugins provide:**
- **Reusable capabilities**: Package event handlers into bundles
- **Simple pattern**: A plugin is just a list of event handlers
- **Easy composition**: Combine multiple plugins together
- **Built-in plugins**: re_act, eval, system_reminder, image_result_formatter, and more
**Built-in plugins** are ready to use:
```python
from connectonion.useful_plugins import re_act, system_reminder
agent = Agent("assistant", tools=[search], plugins=[re_act, system_reminder])
```
[Learn more about plugins](docs/plugin.md) | [Built-in plugins](docs/useful_plugins/)
## π§ Core Concepts
### Agent
The main class that orchestrates LLM calls and tool usage. Each agent:
- Has a unique name for tracking purposes
- Can be given a custom personality via `system_prompt`
- Automatically converts functions to tools
- Records all behavior to JSON files
### Function-Based Tools
**NEW**: Just write regular Python functions! ConnectOnion automatically converts them to tools:
```python
def my_tool(param: str, optional_param: int = 10) -> str:
"""This docstring becomes the tool description."""
return f"Processed {param} with value {optional_param}"
# Use it directly - no wrapping needed!
agent = Agent("assistant", tools=[my_tool])
```
Key features:
- **Automatic Schema Generation**: Type hints become OpenAI function schemas
- **Docstring Integration**: First line becomes tool description
- **Parameter Handling**: Supports required and optional parameters
- **Type Conversion**: Handles different return types automatically
### System Prompts
Define your agent's personality and behavior with flexible input options:
```python
# 1. Direct string prompt
agent = Agent(
name="helpful_tutor",
system_prompt="You are an enthusiastic teacher who loves to educate.",
tools=[my_tools]
)
# 2. Load from file (any text file, no extension restrictions)
agent = Agent(
name="support_agent",
system_prompt="prompts/customer_support.md" # Automatically loads file content
)
# 3. Using Path object
from pathlib import Path
agent = Agent(
name="coder",
system_prompt=Path("prompts") / "senior_developer.txt"
)
# 4. None for default prompt
agent = Agent("basic_agent") # Uses default: "You are a helpful assistant..."
```
Example prompt file (`prompts/customer_support.md`):
```markdown
# Customer Support Agent
You are a senior customer support specialist with expertise in:
- Empathetic communication
- Problem-solving
- Technical troubleshooting
## Guidelines
- Always acknowledge the customer's concern first
- Look for root causes, not just symptoms
- Provide clear, actionable solutions
```
### Logging
Automatic logging of all agent activities including:
- User inputs and agent responses
- LLM calls with timing
- Tool executions with parameters and results
- Default storage in `.co/logs/{name}.log` (human-readable format)
## π― Example Tools
You can still use the traditional Tool class approach, but the new functional approach is much simpler:
### Traditional Tool Classes (Still Supported)
```python
from connectonion.tools import Calculator, CurrentTime, ReadFile
agent = Agent("assistant", tools=[Calculator(), CurrentTime(), ReadFile()])
```
### New Function-Based Approach (Recommended)
```python
def calculate(expression: str) -> float:
"""Perform mathematical calculations."""
return eval(expression) # Use safely in production
def get_time(format: str = "%Y-%m-%d %H:%M:%S") -> str:
"""Get current date and time."""
from datetime import datetime
return datetime.now().strftime(format)
def read_file(filepath: str) -> str:
"""Read contents of a text file."""
with open(filepath, 'r') as f:
return f.read()
# Use them directly!
agent = Agent("assistant", tools=[calculate, get_time, read_file])
```
The function-based approach is simpler, more Pythonic, and easier to test!
## π¨ CLI Templates
ConnectOnion CLI provides templates to get you started quickly:
```bash
# Create a minimal agent (default)
co create my-agent
# Create with specific template
co create my-playwright-bot --template playwright
# Initialize in existing directory
co init # Adds .co folder only
co init --template playwright # Adds full template
```
**Available Templates:**
- `minimal` (default) - Simple agent starter
- `playwright` - Web automation with browser tools
- `meta-agent` - Development assistant with docs search
- `web-research` - Web research and data extraction
Each template includes:
- Pre-configured agent ready to run
- Automatic API key setup
- Embedded ConnectOnion documentation
- Git-ready `.gitignore`
Learn more in the [CLI Documentation](docs/cli/) and [Templates Guide](docs/templates/).
## π¨ Creating Custom Tools
The simplest way is to use functions (recommended):
```python
def weather(city: str) -> str:
"""Get current weather for a city."""
# Your weather API logic here
return f"Weather in {city}: Sunny, 22Β°C"
# That's it! Use it directly
agent = Agent(name="weather_agent", tools=[weather])
```
Or use the Tool class for more control:
```python
from connectonion.tools import Tool
class WeatherTool(Tool):
def __init__(self):
super().__init__(
name="weather",
description="Get current weather for a city"
)
def run(self, city: str) -> str:
return f"Weather in {city}: Sunny, 22Β°C"
def get_parameters_schema(self):
return {
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name"}
},
"required": ["city"]
}
agent = Agent(name="weather_agent", tools=[WeatherTool()])
```
## π Project Structure
```
connectonion/
βββ connectonion/
β βββ __init__.py # Main exports
β βββ agent.py # Agent class
β βββ tools.py # Tool interface and built-ins
β βββ llm.py # LLM interface and OpenAI implementation
β βββ console.py # Terminal output and logging
β βββ cli/ # CLI module
β βββ main.py # CLI commands
β βββ docs.md # Embedded documentation
β βββ templates/ # Agent templates
β βββ basic_agent.py
β βββ chat_agent.py
β βββ data_agent.py
β βββ *.md # Prompt templates
βββ docs/ # Documentation
β βββ quickstart.md
β βββ concepts/ # Core concepts
β βββ cli/ # CLI commands
β βββ templates/ # Project templates
β βββ ...
βββ examples/
β βββ basic_example.py
βββ tests/
β βββ test_agent.py
βββ pyproject.toml
```
## π§ͺ Running Tests
```bash
python -m pytest tests/
```
Or run individual test files:
```bash
python -m unittest tests.test_agent
```
## π Automatic Logging
All agent activities are automatically logged to:
```
.co/logs/{agent_name}.log # Default location
```
Each log entry includes:
- Timestamp
- User input
- LLM calls with timing
- Tool executions with parameters and results
- Final responses
Control logging behavior:
```python
# Default: logs to .co/logs/assistant.log
agent = Agent("assistant")
# Log to current directory
agent = Agent("assistant", log=True) # β assistant.log
# Disable logging
agent = Agent("assistant", log=False)
# Custom log file
agent = Agent("assistant", log="my_logs/custom.log")
```
## π Configuration
### OpenAI API Key
Set your API key via environment variable:
```bash
export OPENAI_API_KEY="your-api-key-here"
```
Or pass directly to agent:
```python
agent = Agent(name="test", api_key="your-api-key-here")
```
### Model Selection
```python
agent = Agent(name="test", model="gpt-5") # Default: gpt-5-mini
```
### Iteration Control
Control how many tool calling iterations an agent can perform:
```python
# Default: 10 iterations (good for most tasks)
agent = Agent(name="assistant", tools=[...])
# Complex tasks may need more iterations
research_agent = Agent(
name="researcher",
tools=[search, analyze, summarize, write_file],
max_iterations=25 # Allow more steps for complex workflows
)
# Simple agents can use fewer iterations for safety
calculator = Agent(
name="calc",
tools=[calculate],
max_iterations=5 # Prevent runaway calculations
)
# Per-request override for specific complex tasks
result = agent.input(
"Analyze all project files and generate comprehensive report",
max_iterations=50 # Override for this specific task
)
```
When an agent reaches its iteration limit, it returns:
```
"Task incomplete: Maximum iterations (10) reached."
```
**Choosing the Right Limit:**
- **Simple tasks (1-3 tools)**: 5-10 iterations
- **Standard workflows**: 10-15 iterations (default: 10)
- **Complex analysis**: 20-30 iterations
- **Research/multi-step**: 30+ iterations
## π οΈ Advanced Usage
### Multiple Tool Calls
Agents can chain multiple tool calls automatically:
```python
result = agent.input(
"Calculate 15 * 8, then tell me what time you did this calculation"
)
# Agent will use calculator first, then current_time tool
```
### Custom LLM Providers
```python
from connectonion.llm import LLM
class CustomLLM(LLM):
def complete(self, messages, tools=None):
# Your custom LLM implementation
pass
agent = Agent(name="test", llm=CustomLLM())
```
## β FAQ
### What is ConnectOnion?
ConnectOnion is a simple, elegant open-source Python framework for production-ready AI agents. It gives you everything around LLM calls β just write prompt and tools.
### What is ConnectOnion's philosophy?
"Keep simple things simple, make complicated things possible." This principle drives every design decision β start simple, add complexity only when needed.
### How do I get started?
```bash
pip install connectonion
```
Or use the CLI for faster setup:
```bash
co create my-agent
cd my-agent
python agent.py
```
### What LLM providers does ConnectOnion support?
ConnectOnion supports multiple providers: OpenAI (default), Anthropic, Gemini, Groq, Grok, OpenRouter. Set via environment variable:
```bash
export OPENAI_API_KEY="your-key"
```
### How do I add tools to my agent?
Just write regular Python functions! ConnectOnion automatically converts them to tools:
```python
def search(query: str) -> str:
"""Search for information."""
return f"Results for {query}"
agent = Agent(name="assistant", tools=[search])
```
No schema writing, no wrapping β your function becomes a tool.
### What are plugins?
Plugins are lists of lifecycle hooks that inject logic at any point in the agent execution cycle. Built-in plugins:
- `re_act`: Reflect + plan after each tool call
- `auto_compact`: Auto-compress context at 90% capacity
- `subagents`: Spawn sub-agents with independent tools
- `ulw`: Ultra Light Work β fully autonomous mode
```python
from connectonion.useful_plugins import re_act, subagents
agent = Agent("researcher", tools=[search], plugins=[re_act, subagents])
```
### What is `@xray` debugging?
`@xray` is an interactive debugging feature that pauses execution at marked tools:
```python
from connectonion.decorators import xray
@xray
def my_tool(query: str) -> str:
return "result"
agent = Agent("assistant", tools=[my_tool])
agent.auto_debug()
```
At each breakpoint, you can:
- Inspect local variables
- Edit values to test "what if" scenarios
- Continue execution
- Run Python REPL
### What is the Skills System?
Skills are reusable workflows with automatic permission scoping and three-level auto-discovery:
- `.co/skills/skill-name/SKILL.md` (project-level, highest priority)
- `~/.co/skills/skill-name/SKILL.md` (user-level)
- `builtin/skill-name/SKILL.md` (built-in)
Automatically loads Claude Code skills from `.claude/skills/` β no conversion needed.
### What is the Multi-Agent Trust System?
When agents call each other, trust decisions happen **before LLM involvement** (zero token cost):
```python
agent = Agent(name="production", trust="careful")
```
Three presets:
- `open` (dev): Allow all
- `careful` (staging): whitelist β allow, unknown β ask LLM, blocked β deny
- `strict` (production): Enforce strict rules
### What built-in tools are available?
Ready-to-use tools with no schema writing:
```python
from connectonion import bash, Shell, Gmail, Outlook, GoogleCalendar, Memory, TodoList
from connectonion.useful_tools import FileTools
from connectonion.useful_tools.browser_tools import BrowserAutomation
```
### Where can I find help?
- **[Documentation](http://docs.connectonion.com)**: Comprehensive guides
- **[Discord](https://discord.gg/4xfD9k8AUF)**: 1000+ builders community
- **[GitHub Issues](https://github.com/openonion/connectonion/issues)**: Bug reports
---
## πΊοΈ Roadmap
**Current Focus:**
- Multi-agent networking (serve/connect)
- Trust system for agent collaboration
- `co deploy` for one-command deployment
**Recently Completed:**
- Multiple LLM providers (OpenAI, Anthropic, Gemini, Groq, Grok, OpenRouter)
- Managed API keys (`co/` prefix)
- Plugin system
- Google OAuth integration
- Interactive debugging (`@xray`, `auto_debug`)
See [full roadmap](docs/roadmap.md) for details.
## π Connect With Us
[](https://discord.gg/4xfD9k8AUF)
[](https://github.com/openonion/connectonion)
[](http://docs.connectonion.com)
- **π¬ Discord**: [Join our community](https://discord.gg/4xfD9k8AUF) - Get help, share ideas, meet other developers
- **π Documentation**: [docs.connectonion.com](http://docs.connectonion.com) - Comprehensive guides and examples
- **β GitHub**: [Star the repo](https://github.com/openonion/connectonion) - Show your support
- **π Issues**: [Report bugs](https://github.com/openonion/connectonion/issues) - We respond quickly
---
## β Show Your Support
If ConnectOnion helps you build better agents, **give it a star!** β
It helps others discover the framework and motivates us to keep improving it.
[β Star on GitHub](https://github.com/openonion/connectonion)
---
## π€ Contributing
We welcome contributions! ConnectOnion is open source and community-driven.
1. Fork the repository
2. Create a feature branch
3. Add tests for new functionality
4. Submit a pull request
See our [Contributing Guide](http://docs.connectonion.com/website-maintenance) for more details.
---
## π License
MIT License - Use it anywhere, even commercially. See [LICENSE](LICENSE) file for details.
---
**Built with β€οΈ by the open-source community**
[β Star this repo](https://github.com/openonion/connectonion) β’ [π¬ Join Discord](https://discord.gg/4xfD9k8AUF) β’ [π Read Docs](https://docs.connectonion.com) β’ [β¬ Back to top](#-connectonion)
## β Frequently Asked Questions (FAQ)
### What is ConnectOnion?
ConnectOnion is a simple, elegant framework for production-ready AI agents. Philosophy: "Keep simple things simple, make complicated things possible" - you write prompts and tools, framework handles everything else.
### Key Features
| Feature | Description |
|---------|-------------|
| Built-in AI Programmer | `co ai` - AI coding assistant |
| Built-in Frontend & Backend | chat.openonion.ai ready-to-use |
| Ready-to-Use Tools | Import without schema writing |
| Approval System | Dangerous ops auto-trigger approval |
| Skills System | Claude Code compatible, auto-discovery |
| 12 Lifecycle Hooks | Inject logic at any point |
| Plugin System | re_act, auto_compact, subagents, ulw |
| Multi-Agent Trust | Fast rules, zero token cost |
### Quick Start
```bash
pip install connectonion
```
### Available Tools
bash, Shell, FileTools, BrowserAutomation, Gmail, Outlook, GoogleCalendar, Memory, TodoList
### Customize Tools
```bash
co copy Gmail # Copy tool source for modification
```
### Built-in Plugins
| Plugin | Description | Claude Code Equivalent |
|--------|-------------|------------------------|
| re_act | Reflect + plan after each tool | - |
| auto_compact | Auto-compress context at 90% | Context compression |
| subagents | Spawn sub-agents | Sub-agent spawning |
| ulw | Ultra Light Work autonomous | Autonomous mode |
### Skills Auto-Discovery
Project β User β Built-in levels. Automatically loads Claude Code skills from `.claude/skills/`.
### Lifecycle Hooks
after_user_input, before_iteration, before_llm, after_llm, before_tools, after_tools, on_error, after_iteration, on_stop_signal, on_complete
### Trust System Presets
open (dev), careful (staging), strict (production)
### Debug Agent
```python
agent.auto_debug() # Interactive debugging
```
### Deploy Agent
```python
from connectonion import host
host(agent) # HTTP + P2P relay
```
### Requirements
Python 3.10+
### License
MIT
### Help Resources
[Docs](http://docs.connectonion.com) | [Discord](https://discord.gg/4xfD9k8AUF) | [Issues](https://github.com/openonion/connectonion/issues)