跳到正文
GitHub·· 7 天前AI 评分34

Onyx:可自主上网学习技能的自学习 AI 智能体

VulnSeeker/onyx-self-learning-agent

AI 导读

VulnSeeker 开源了自学习 AI 智能体 Onyx,接到任务后会分析所需技能、比对已有知识库,并从网上自动学习缺失技能,再组合完成端到端任务。它支持任务驱动、指定技能和模型训练三种模式,提供 CLI、FastAPI REST API 与 Streamlit 界面,采用 MIT 许可。

正文
# Onyx — Self-Learning AI Agent

> An autonomous agent that researches the web to build its own skill 
> knowledge bases, then executes multi-skill tasks end-to-end.

📖 **Read the story behind Onyx:**
- [LinkedIn Article](https://www.linkedin.com/pulse/i-built-self-learning-ai-agent-from-scratch-heres-what-mubbshra-iqbal-xl6he)
- [Medium Article](https://medium.com/@mubashraiqbal.pk/i-built-a-self-learning-ai-agent-from-scratch-heres-what-i-learned-672d59621459)

[![CI](https://github.com/VulnSeeker/onyx-self-learning-agent/actions/workflows/ci.yml/badge.svg)](https://github.com/VulnSeeker/onyx-self-learning-agent/actions/workflows/ci.yml)
[![Docker](https://github.com/VulnSeeker/onyx-self-learning-agent/actions/workflows/docker.yml/badge.svg)](https://github.com/VulnSeeker/onyx-self-learning-agent/actions/workflows/docker.yml)
[![Python 3.10+](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
[![Typing: mypy](https://img.shields.io/badge/typing-mypy-blue.svg)](https://mypy-lang.org/)
[![Tests](https://img.shields.io/badge/tests-40%20passed-brightgreen.svg)](https://github.com/VulnSeeker/onyx-self-learning-agent/actions)

Onyx is a self-learning agent that acquires skills on demand. Give it a 
task — it analyzes what skills are needed, checks its existing knowledge 
base, learns any missing skills from the web, and combines everything to 
complete the task with working code.

No manual skill configuration. No pre-loaded knowledge. Just a task.

---

## Table of Contents

- [What It Does](#what-it-does)
- [Demo](#demo)
- [Quick Start](#quick-start)
- [Usage](#usage)
- [Architecture](#architecture)
- [API Reference](#api-reference)
- [Configuration](#configuration)
- [Project Structure](#project-structure)
- [Development](#development)
- [Roadmap](#roadmap)
- [Contributing](#contributing)
- [License](#license)

---

## What It Does

Onyx operates in three modes:

### 1. Task-Driven (Autonomous)

```bash
onyx task "Write a Python script that reads a JSON file and pretty-prints it with sorted keys"

The agent will:

  1. Analyze the task → identifies required skills (Python, JSON, File I/O)
  2. Match against existing skills in the registry
  3. Learn any missing skills from the web automatically
  4. Retrieve relevant knowledge from all matched skills
  5. Execute the task (with sandboxed code when needed)
  6. Compose the final answer, citing each skill used

2. Skill-Scoped (Explicit)

onyx learn "Python asyncio"
onyx run python_asyncio "Write a basic asyncio example that runs 3 tasks concurrently"

3. Model Training

onyx train "Train a text classifier to detect toxic comments"

Plans a training pipeline, downloads a public dataset, trains a small model, and reports the metric.


Demo

Real output from a running Onyx instance is available in the demo/ folder. Every JSON file there is auto-generated by the agent — nothing is hand-written.

Skills learned in the latest run:

Skill Entries Task Executed
open_source_intelligence_osint 20 OSINT tool categories for email discovery
linux_command_line 12 Bash one-liner for largest files
python_decorators 11 Decorator that logs function calls
python_asyncio 10 Concurrent task execution
dockerfile_for_python_flask 8 Minimal Dockerfile for a Flask app
json 10 JSON parsing and formatting
file_i_o 18 File reading and validation

Sample from a real run:

$ onyx task "Write a Python script that reads a JSON file and pretty-prints it with sorted keys"

Analyzing task...
  Required skills: Python, JSON, File I/O
  Matching: Python
    ✅ Matched -> python_decorators (conf 0.90)
  Matching: JSON
    📚 Learning new skill: JSON
    ✅ Learned -> json (10 entries)
  Matching: File I/O
    📚 Learning new skill: File I/O
    ✅ Learned -> file_i_o (18 entries)
Retrieving combined knowledge...
Executing via primary skill: python_decorators
  Generating code...
  Running code in sandbox...
Composing final answer...
Done in 85.2s

[final answer with working script, citations to each skill, and sandbox output]

Quick Start

Option A: Google Colab (Free, No Setup)

Run this in a Colab cell:

!git clone https://github.com/VulnSeeker/onyx-self-learning-agent.git
%cd onyx-self-learning-agent

!pip install -e ".[api]" -q

# Set your API key
import os
os.environ["OPENAI_API_KEY"] = "sk-your-key-here"
os.environ["DATA_DIR"] = "/content/onyx-data"

# Run a task
!onyx task "Write a Python function that sorts a list of dictionaries by a given key"

Option B: Local Install

# Clone
git clone https://github.com/VulnSeeker/onyx-self-learning-agent.git
cd onyx-self-learning-agent

# Install
pip install -e ".[api,dev]"

# Configure
cp .env.example .env
# Edit .env and add your OPENAI_API_KEY

# Verify
onyx info

Option C: Docker

# Build
docker build -t onyx:latest .

# Run
docker run --rm -p 8000:8000 --env-file .env onyx:latest

# Test
curl http://localhost:8000/health

Usage

CLI Commands

Command Description
onyx task "<task>" Execute a task end-to-end (auto-learn + multi-skill)
onyx learn <skill> Bootstrap a specific skill from web research
onyx run <skill> <task> Execute a task using a specific skill
onyx skills List all learned skills
onyx show <skill> Show details and knowledge entries for a skill
onyx delete <skill> Delete a skill and its knowledge base
onyx train "<task>" Plan and train a small ML model
onyx serve Launch the FastAPI service
onyx web Launch the Streamlit dashboard
onyx info Show current configuration
onyx version Show version

Python Library

from onyx import Onyx

agent = Onyx()

# Task-driven (autonomous)
result = agent.task(
    "Write a Python script that fetches a URL and extracts all links"
)
print(result.answer)

# Skill-scoped (explicit)
agent.learn("Python asyncio")
result = agent.run("python_asyncio", "Write a rate-limited HTTP client")
print(result.answer)

# Access the knowledge base
for skill in agent.skills():
    print(f"{skill.skill_id}: {skill.entry_count} entries")

REST API

Start the service:

onyx serve --host 0.0.0.0 --port 8000

Then:

# Submit a task (returns job ID)
curl -X POST http://localhost:8000/task \
  -H "Content-Type: application/json" \
  -d '{"task": "Write a bash one-liner to count unique lines"}'

# Poll for result
curl http://localhost:8000/task/<job_id>

# List skills
curl http://localhost:8000/skills

# Health check
curl http://localhost:8000/health

Interactive API docs available at http://localhost:8000/docs.


Architecture

Onyx is organized as a layered system:

┌──────────────────────────────────────────────────────┐
│                    INTERFACES                        │
│  CLI (argparse)  │  REST API (FastAPI)  │  Web (Streamlit)  │
└───────────────────────┬──────────────────────────────┘
                        │
┌───────────────────────▼──────────────────────────────┐
│              TASK ORCHESTRATOR                       │
│  analyze → match skills → auto-learn → execute       │
│  → combine knowledge → compose answer                │
└───────────────────────┬──────────────────────────────┘
                        │
        ┌───────────────┼───────────────┐
        ▼               ▼               ▼
┌───────────────┐ ┌──────────────┐ ┌──────────────┐
│  BOOTSTRAPPER │ │   RUNTIME    │ │ MODEL BUILDER│
│  (learn new   │ │ (execute     │ │ (train small │
│   skills)     │ │  tasks)      │ │  ML models)  │
└───────┬───────┘ └──────┬───────┘ └──────┬───────┘
        │                │                │
        ▼                ▼                ▼
┌──────────────────────────────────────────────────────┐
│                  I/O LAYER                           │
│  LLM client │ Web search │ Crawler │ Sandbox         │
└───────────────────────┬──────────────────────────────┘
                        │
┌───────────────────────▼──────────────────────────────┐
│                    STORAGE                           │
│  SQLite registry  │  ChromaDB vectors  │  File store │
└──────────────────────────────────────────────────────┘

Core Modules

Module Responsibility
agent.py Top-level Onyx facade
orchestrator.py Task → skills → execution pipeline
bootstrapper.py Web research → knowledge base
runtime.py Skill-scoped task execution
model_builder.py Small ML model planning + training
llm.py OpenAI-compatible client with retries
search.py Tavily / DuckDuckGo search backend
crawler.py robots.txt-aware HTML crawler
sandbox.py Sandboxed Python execution
storage.py SQLite registry + ChromaDB vectors
api.py FastAPI service
cli.py Command-line interface

How Self-Learning Works

  1. Spec generation: LLM generates a structured skill spec (subtopics, tools, keywords)
  2. Source discovery: Web search finds 3–12 high-quality sources
  3. Extraction: LLM extracts structured knowledge entries (facts, procedures, code, tools)
  4. Deduplication: Two-tier dedupe (embedding distance + LLM verdict) avoids duplicates
  5. Storage: Entries stored in per-skill ChromaDB collections
  6. Retrieval: At runtime, relevant entries retrieved via semantic search
  7. Gap detection: Runtime detects missing knowledge and updates the skill DB

API Reference

POST /task

Submit a task for asynchronous execution.

Request:

{
  "task": "Write a Python script that parses a CSV file",
  "auto_learn": true
}

Response (202 Accepted):

{
  "job_id": "abc123def456",
  "status": "queued",
  "poll_url": "http://localhost:8000/task/abc123def456"
}

GET /task/{job_id}

Poll for task status and result.

Response:

{
  "job_id": "abc123def456",
  "task": "Write a Python script...",
  "status": "done",
  "elapsed_seconds": 42.3,
  "result": {
    "answer": "...",
    "code_output": "...",
    "skill_matches": [...]
  }
}

GET /skills

List all learned skills.

GET /skills/{skill_id}

Get details and knowledge entries for a specific skill.

DELETE /skills/{skill_id}

Delete a skill and its knowledge base.

GET /health

Liveness and readiness probe.


Configuration

All configuration is via environment variables (see .env.example).

Required

Variable Description
OPENAI_API_KEY API key for any OpenAI-compatible provider

LLM Provider (Optional)

Variable Default Description
OPENAI_BASE_URL https://api.openai.com/v1 Provider endpoint
LLM_MODEL gpt-4o-mini Chat model
EMBED_MODEL text-embedding-3-small Embedding model

Supported providers:

  • OpenAI (default)
  • Groq (free tier: openai/gpt-oss-20b)
  • Together AI
  • Ollama (local, no API key)
  • OpenRouter

Search (Optional)

Variable Default Description
TAVILY_API_KEY (empty) Tavily key; DuckDuckGo used if empty

Storage (Optional)

Variable Default Description
DATA_DIR ./data Where runtime data is stored
LOG_LEVEL INFO Logging verbosity

Behaviour Tuning (Optional)

Variable Default Description
MAX_SOURCES_PER_SKILL 12 Web sources per skill bootstrap
MAX_PAGES_PER_SOURCE 1 Pages fetched per source
REQUEST_TIMEOUT 20 HTTP timeout in seconds
CODE_TIMEOUT 20 Sandbox execution timeout
DEDUPE_DISTANCE 0.12 Cosine distance threshold for dedupe
MAX_CHARS_PER_PAGE 12000 Max characters extracted per page

API Service (Optional)

Variable Default Description
ONYX_API_TOKEN (empty) Bearer token; auth disabled if empty
ONYX_CORS_ORIGINS * Comma-separated allowed origins
ONYX_JOB_TTL_SECONDS 3600 Job retention window

Project Structure

onyx-self-learning-agent/
├── .github/workflows/         # CI + Docker workflows
├── demo/                      # Real auto-generated JSON exports
├── src/onyx/                  # Main package
│   ├── __init__.py
│   ├── agent.py               # Onyx facade
│   ├── orchestrator.py        # Task orchestration
│   ├── bootstrapper.py        # Skill learning
│   ├── runtime.py             # Task execution
│   ├── model_builder.py       # ML training
│   ├── llm.py                 # LLM client
│   ├── search.py              # Web search
│   ├── crawler.py             # HTML crawler
│   ├── sandbox.py             # Code sandbox
│   ├── storage.py             # SQLite + Chroma
│   ├── schemas.py             # Pydantic models
│   ├── config.py              # Configuration
│   ├── api.py                 # FastAPI service
│   ├── cli.py                 # CLI entry point
│   └── web.py                 # Streamlit dashboard
├── tests/                     # Pytest suite
├── Dockerfile                 # Production container
├── docker-compose.yml         # Local dev stack
├── pyproject.toml             # Package + tooling config
├── requirements.txt           # Runtime deps
├── requirements-dev.txt       # Dev deps
├── .env.example               # Environment template
└── README.md

Development

Setup

# Clone
git clone https://github.com/VulnSeeker/onyx-self-learning-agent.git
cd onyx-self-learning-agent

# Install dev dependencies
pip install -e ".[api,dev]"

# Copy env template
cp .env.example .env
# Edit .env with your API key

Running Tests

# Run all tests
pytest

# With coverage report
pytest --cov=onyx --cov-report=term-missing

# Just unit tests
pytest -m unit

Linting

# Check for issues
ruff check src tests

# Auto-fix where possible
ruff check --fix src tests

# Check formatting
ruff format --check src tests

Type Checking

mypy src

Pre-commit Hooks

pre-commit install

Roadmap

  • Web research → knowledge base pipeline
  • Sandboxed code execution
  • Multi-skill task orchestration
  • FastAPI REST service
  • Docker + docker-compose
  • CI/CD workflows (green)
  • Test suite (40 tests passing)
  • Render / Fly.io deployment
  • Approval queue for knowledge updates
  • Graph memory for entity relations
  • Multi-agent collaboration

Contributing

Contributions welcome. To get started:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Run ruff check src tests and pytest to verify
  5. Commit (git commit -m 'feat: add amazing feature')
  6. Push (git push origin feature/amazing-feature)
  7. Open a pull request

Please open an issue before submitting a pull request for substantial changes.


Requirements

  • Python 3.10, 3.11, or 3.12
  • An OpenAI-compatible LLM API key
  • (Optional) Docker for containerized deployment
  • (Optional) Tavily API key for improved search quality

License

MIT License — see LICENSE for details.


Author

VulnSeeker


If you find this project useful, consider starring the repository.

来源:GitHub · github.com