An intelligent agent for task automation and assistance
Project description
OnIt
OnIt — the AI is working on the given task and will deliver the results shortly.
OnIt is an intelligent agent framework for task automation and assistance. It is built on MCP (Model Context Protocol) for tool integration and supports the A2A (Agent-to-Agent) protocol for multi-agent communication. OnIt connects to LLMs via any OpenAI-compatible API (private vLLM servers or OpenRouter.ai) and orchestrates tasks through modular MCP servers.
Quick Guide
1. Install
pip install onit==0.1.2
Or from source:
git clone https://github.com/sibyl-oracles/onit.git
cd onit
pip install -e ".[all]" --upgrade
2. Configure
Set your LLM host and at least one API key:
# Option A: Private vLLM server
export ONIT_HOST=http://localhost:8000/v1
# Option B: OpenRouter.ai
export ONIT_HOST=https://openrouter.ai/api/v1
export OPENROUTER_API_KEY=sk-or-v1-your-key-here
Optional API keys for built-in tools:
export OLLAMA_API_KEY=your_key # Web search. Best to enable this. Free rate limited.
export OPENWEATHER_API_KEY=your_key # Weather data. Free.
Get your free API keys: Ollama | OpenWeatherMap
3. Run
onit
That's it. MCP servers start automatically, and you get an interactive terminal chat with tool access.
Other interfaces:
onit --web # Gradio web UI on port 9000
onit --gateway # Telegram bot gateway
onit --a2a # A2A server on port 9001
onit --client --task "your task" # Send a task to an A2A server and print the answer
Configuration
All options can be set via CLI flags, environment variables, or a YAML config file:
onit --config configs/default.yaml
Example config (configs/default.yaml):
serving:
host: https://openrouter.ai/api/v1
host_key: sk-or-v1-your-key-here # or set OPENROUTER_API_KEY env var
model: google/gemini-2.5-pro
think: true
max_tokens: 262144
verbose: false
timeout: 600
# prompt_intro: "I am a helpful AI assistant. My name is OnIt."
web: false
web_port: 9000
mcp:
servers:
- name: PromptsMCPServer
url: http://127.0.0.1:18200/sse
enabled: true
- name: ToolsMCPServer
url: http://127.0.0.1:18201/sse
enabled: true
The LLM provider is auto-detected from the host URL. If it contains openrouter.ai, the API key is read from host_key or OPENROUTER_API_KEY. All other hosts default to vLLM with no key required.
CLI Options
General:
| Flag | Description | Default |
|---|---|---|
--config |
Path to YAML configuration file | configs/default.yaml |
--host |
LLM serving host URL (overrides config and ONIT_HOST env var) |
— |
--model |
Model name (overrides serving.model in config) |
— |
--verbose |
Enable verbose logging | false |
--timeout |
Request timeout in seconds (-1 = none) |
600 |
--template-path |
Path to custom prompt template YAML file | — |
--prompt-intro |
Custom system prompt intro for the model | "I am a helpful AI assistant. My name is OnIt." |
Text UI:
| Flag | Description | Default |
|---|---|---|
--text-theme |
Text UI theme (white or dark) |
dark |
--text-show-logs |
Show execution logs panel | false |
Web UI:
| Flag | Description | Default |
|---|---|---|
--web |
Launch Gradio web UI | false |
--web-port |
Gradio web UI port | 9000 |
Telegram Gateway:
| Flag | Description | Default |
|---|---|---|
--gateway |
Run as a Telegram bot gateway (requires TELEGRAM_BOT_TOKEN env var) |
false |
A2A (Agent-to-Agent):
| Flag | Description | Default |
|---|---|---|
--a2a |
Run as an A2A protocol server | false |
--a2a-port |
A2A server port | 9001 |
--client, --a2a-client |
Client mode: send a task to a remote A2A server | false |
--a2a-host |
A2A server URL for client mode | http://localhost:9001 |
--task, --a2a-task |
Task string for A2A loop or client mode | — |
--file, --a2a-file |
File to upload to the A2A server with the task | — |
--image, --a2a-image |
Image file to send for vision processing | — |
--loop, --a2a-loop |
Enable A2A loop mode | false |
--period, --a2a-period |
Seconds between A2A loop iterations | 10 |
MCP (Model Context Protocol):
| Flag | Description | Default |
|---|---|---|
--mcp-host |
Override the host/IP in all MCP server URLs (e.g. 192.168.1.100) |
— |
--mcp-sse |
URL of an external MCP tools server using SSE transport (can be repeated) | — |
Features
Interactive Chat
Rich terminal UI with input history, theming, and execution logs. Press Enter or Ctrl+C to interrupt any running task.
Web UI
Gradio-based browser interface with file upload, copy buttons, and real-time polling:
onit --web --web-port 9000
Supports optional Google OAuth2 authentication — see docs/WEB_AUTHENTICATION.md.
MCP Tool Integration
MCP servers are started automatically. Tools are auto-discovered and available to the agent.
| Server | Description |
|---|---|
| PromptsMCPServer | Prompt templates for instruction generation |
| ToolsMCPServer | Web search, bash commands, file operations, and document tools |
Connect to additional external MCP servers:
onit --mcp-sse http://localhost:8080/sse --mcp-sse http://192.168.1.50:9090/sse
Telegram Gateway
Chat with OnIt remotely from the Telegram mobile app using a Telegram bot.
Setup:
- Create a bot with BotFather on Telegram (
/newbot) and copy the token. - Set the token and start the gateway:
export TELEGRAM_BOT_TOKEN=your-bot-token-here
onit --gateway
- Open Telegram, find your bot, and send a message. OnIt will respond using the full agent with all its tools.
You can also send photos — the bot will pass them to the LLM for vision processing (if your model supports it). The photo caption is used as the prompt (defaults to "Describe this image." if no caption is provided).
Install the gateway dependency separately if not using [all]:
pip install "onit[gateway]"
A2A Protocol
Run OnIt as an A2A server so other agents can send tasks:
onit --a2a --a2a-port 9001
The agent card is available at http://localhost:9001/.well-known/agent.json.
Send a task via CLI:
onit --client --a2a-host http://192.168.86.101:9001 --task "what is the weather in Manila"
Send a task via Python (A2A SDK):
from a2a.client import ClientFactory, create_text_message_object
from a2a.types import Role
import asyncio
async def main():
client = await ClientFactory.connect("http://localhost:9001")
message = create_text_message_object(role=Role.user, content="What is the weather?")
async for event in client.send_message(message):
print(event)
asyncio.run(main())
Send a task with an image (VLM):
# Server
onit --a2a --host <ONIT_HOST> --model Qwen/Qwen3-VL-8B-Instruct
# Client
onit --client --task "are the rambutans ripe?" --a2a-image assets/rambutan_calamansi.jpg
Send an image task via Python (A2A SDK):
import asyncio, base64, os, uuid
from a2a.client import ClientFactory
from a2a.types import FilePart, FileWithBytes, Message, Part, Role, TextPart
async def main():
image_path = "assets/rambutan_calamansi.jpg"
with open(image_path, "rb") as f:
image_data = base64.b64encode(f.read()).decode("utf-8")
message = Message(
role=Role.user,
message_id=str(uuid.uuid4()),
parts=[
Part(root=TextPart(text="Are the rambutans ripe enough to be eaten?")),
Part(root=FilePart(file=FileWithBytes(
bytes=image_data,
mime_type="image/jpeg",
name=os.path.basename(image_path),
))),
],
)
client = await ClientFactory.connect("http://localhost:9001")
async for event in client.send_message(message):
print(event)
asyncio.run(main())
Loop Mode
Repeat a task on a configurable timer (useful for monitoring):
onit --a2a-loop --task "Check the weather in Manila" --a2a-period 60
Custom Prompt Templates
Create a YAML file with an instruction_template field:
# my_template.yaml
instruction_template: |
You are a research assistant. Think step by step.
<task>
{task}
</task>
Save all results to `{data_path}`.
Session ID: {session_id}
Then use it:
onit --template-path my_template.yaml
See example templates in src/mcp/prompts/prompt_templates/.
Model Serving
Private vLLM
Serve models locally with vLLM:
CUDA_VISIBLE_DEVICES=0,1,2,3 vllm serve Qwen/Qwen3-30B-A3B-Instruct-2507 \
--max-model-len 262144 --port 8000 \
--enable-auto-tool-choice --tool-call-parser qwen3_xml \
--reasoning-parser qwen3 --tensor-parallel-size 4 \
--chat-template-content-format string
export ONIT_HOST=http://localhost:8000/v1
onit
OpenRouter.ai
OpenRouter gives access to models from OpenAI, Google, Meta, Anthropic, and others through a single API.
export OPENROUTER_API_KEY=sk-or-v1-your-key-here
export ONIT_HOST=https://openrouter.ai/api/v1
onit
Browse available models at openrouter.ai/models and use the model ID (e.g. google/gemini-2.5-pro, meta-llama/llama-4-maverick, openai/gpt-4.1).
Design Philosophy
- Portable — Minimal dependencies. Deployable from embedded devices to GPU servers.
- Modular — Clear separation of AI logic, tasks, and UIs. Easily extendable with new MCP servers.
- Scalable — From a single tool to complex multi-server setups.
- Redundant — Multiple ways to solve a problem. Let the AI decide the optimal path.
- Configurable — Edit a YAML file and you are good to go.
- Responsive — Safety routines can interrupt running tasks at any time.
Architecture
┌─────────────────────────────────────────────────────┐
│ onit CLI │
│ (argparse + YAML config) │
└────────────────────────┬────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ OnIt (src/onit.py) │
│ │
│ ┌─────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ ChatUI │ │ WebChatUI│ │ Telegram │ │ A2A │ │
│ │(terminal│ │ (Gradio) │ │ Gateway │ │ Server │ │
│ └────┬────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ └─────────┬─┘ │ │ │
│ ▼ ▼ │
│ client_to_agent() / process_task() │
│ │ │
│ ▼ │
│ MCP Prompt Engineering (FastMCP) │
│ │ │
│ ▼ │
│ chat() ◄──── Tool Registry │
│ (vLLM / OpenRouter) (auto-discovered) │
└─────────────────────────────────────────────────────┘
│
┌────────────┼────────────┐
▼ ▼ ▼
┌───────────┐ ┌──────────┐ ┌──────────┐
│ Prompts │ │ Tools │ │ External │ ...
│ MCP Server│ │MCP Server│ │MCP (SSE) │
└───────────┘ └──────────┘ └──────────┘
Project Structure
onit/
├── configs/
│ └── default.yaml # Agent configuration
├── pyproject.toml # Package configuration
├── src/
│ ├── cli.py # CLI entry point
│ ├── onit.py # Core agent class
│ ├── lib/
│ │ ├── text.py # Text utilities
│ │ └── tools.py # MCP tool discovery
│ ├── mcp/
│ │ ├── prompts/ # Prompt engineering (FastMCP)
│ │ └── servers/ # MCP servers (tools, web, bash, filesystem)
│ ├── model/
│ │ └── serving/
│ │ └── chat.py # LLM interface (vLLM + OpenRouter)
│ ├── ui/
│ │ ├── text.py # Rich terminal UI
│ │ ├── web.py # Gradio web UI
│ │ └── telegram.py # Telegram bot gateway
│ └── test/ # Test suite (pytest)
Documentation
- Testing — Running the test suite
- Docker — Docker and Docker Compose setup
- Web Authentication — Web UI authentication reference
- Web Deployment — Production deployment with HTTP/HTTPS via nginx or Caddy
License
Apache License 2.0. See LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file onit-0.1.2.tar.gz.
File metadata
- Download URL: onit-0.1.2.tar.gz
- Upload date:
- Size: 111.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
59faed21a5495b679861f662fc812e5c6bb50c69faa862cd7b6e01f64ffdc363
|
|
| MD5 |
1f2d6ba020d8b09dc4cf338f9abc2a10
|
|
| BLAKE2b-256 |
8e6914ecc2e557a22d7250d4f59147b837f213b1eacd294006bdc4da27357c04
|
Provenance
The following attestation bundles were made for onit-0.1.2.tar.gz:
Publisher:
publish.yml on sibyl-oracles/onit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
onit-0.1.2.tar.gz -
Subject digest:
59faed21a5495b679861f662fc812e5c6bb50c69faa862cd7b6e01f64ffdc363 - Sigstore transparency entry: 991550354
- Sigstore integration time:
-
Permalink:
sibyl-oracles/onit@588cfaa6dc5e8bb9519f454a28259ce79f432288 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/sibyl-oracles
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@588cfaa6dc5e8bb9519f454a28259ce79f432288 -
Trigger Event:
release
-
Statement type:
File details
Details for the file onit-0.1.2-py3-none-any.whl.
File metadata
- Download URL: onit-0.1.2-py3-none-any.whl
- Upload date:
- Size: 132.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3a3610819cce429d13cbe72606259e94a8fd7950e52bd7e0b414cfd7fed9b687
|
|
| MD5 |
3f1f3208858b93e1fdeddda4b2c26e75
|
|
| BLAKE2b-256 |
173d50c37b7442ff17dc5b0ed797d105cb7b5d947c7028f8ca6c9886d490d8d6
|
Provenance
The following attestation bundles were made for onit-0.1.2-py3-none-any.whl:
Publisher:
publish.yml on sibyl-oracles/onit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
onit-0.1.2-py3-none-any.whl -
Subject digest:
3a3610819cce429d13cbe72606259e94a8fd7950e52bd7e0b414cfd7fed9b687 - Sigstore transparency entry: 991550363
- Sigstore integration time:
-
Permalink:
sibyl-oracles/onit@588cfaa6dc5e8bb9519f454a28259ce79f432288 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/sibyl-oracles
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@588cfaa6dc5e8bb9519f454a28259ce79f432288 -
Trigger Event:
release
-
Statement type: