bot/AGENTS.md
2026-02-11 16:43:05 +01:00

9.1 KiB

AGENTS.md

Overview

This is Antigravity Agent — an autonomous AI agent platform built with a Rust backend and a vanilla JS frontend. Users create "tasks" (goals), and the system dispatches an LLM-powered agent to accomplish them. Tasks can be run on-demand or on a cron schedule. Each execution produces logs and a final answer, all persisted to PostgreSQL.

Architecture

┌─────────────────────────────────────────────────────────┐
│  Frontend (Vite + Vanilla JS)                           │
│  - OAuth login via Authentik                            │
│  - Dashboard: recent runs, task list, logs, answers     │
│  - Polls /api/tasks every 3s for live updates           │
└──────────────────────┬──────────────────────────────────┘
                       │ /api/*
┌──────────────────────▼──────────────────────────────────┐
│  Axum HTTP Server  (src/server/)                        │
│  - CORS, CSP, rate limiting (1 MB body)                 │
│  - Cookie-based + Bearer token auth                     │
│  - Routes: tasks CRUD, runs, auth (callback/refresh)    │
├─────────────────────────────────────────────────────────┤
│  Domain Layer  (src/domain/)                            │
│  ├─ agent/     Agent loop, LLM API client, tool defs    │
│  ├─ auth       JwksVerifier, Authenticator (OIDC)       │
│  └─ tasks      Task execution, run management           │
├─────────────────────────────────────────────────────────┤
│  Scheduler  (src/scheduler.rs)                          │
│  - tokio-cron-scheduler for recurring task execution    │
├─────────────────────────────────────────────────────────┤
│  Entities  (src/entities/)                              │
│  - task, task_run  (SeaORM models)                      │
├─────────────────────────────────────────────────────────┤
│  PostgreSQL                                             │
│  - Migrations managed via sea-orm-migration             │
└─────────────────────────────────────────────────────────┘

Project Structure

bot/
├── Cargo.toml                 # Workspace root (members: ".", "migration")
├── src/
│   ├── main.rs                # Entrypoint: tracing init → server::start()
│   ├── config.rs              # Config struct loaded from env vars
│   ├── error.rs               # AppError enum (thiserror) → Axum responses
│   ├── scheduler.rs           # Cron job scheduler (wraps tokio-cron-scheduler)
│   ├── tests.rs               # Unit tests for error handling & config
│   ├── domain/
│   │   ├── agent/
│   │   │   ├── mod.rs         # Agent struct: agentic loop with turn/time limits
│   │   │   ├── api.rs         # LLM request/response types, Tavily search client
│   │   │   └── tools.rs       # Tool definitions (google_search, finish) & dispatch
│   │   ├── auth.rs            # JwksVerifier (RSA/JWKS), Authenticator (code exchange, refresh)
│   │   └── tasks.rs           # Task execution logic, response DTOs
│   ├── entities/
│   │   ├── task.rs            # SeaORM entity: tasks table
│   │   └── task_run.rs        # SeaORM entity: task_runs table (belongs_to task)
│   └── server/
│       ├── mod.rs             # App bootstrap: DB, scheduler, auth, router, CORS
│       ├── auth.rs            # Auth routes & AuthenticatedUser extractor
│       └── tasks.rs           # Task CRUD & run endpoints
├── migration/
│   └── src/                   # SeaORM migrations (tasks, answer col, runs table, cron col)
├── frontend/
│   ├── index.html             # SPA shell with glassmorphism dark theme
│   ├── src/
│   │   ├── main.js            # All app logic: auth flow, task/run rendering, polling
│   │   └── style.css          # Styles
│   ├── vite.config.js         # Dev proxy: /api → localhost:3000
│   └── package.json           # Deps: vite, marked, dompurify
└── .forgejo/workflows/
    └── pipeline.yaml          # CI: build frontend + cargo build → deploy via systemd

Agent System

The agent (src/domain/agent/) is a turn-based autonomous loop:

  1. A system prompt is injected with the current date and instructions not to ask the user for clarification.
  2. The user's goal is sent as the initial message.
  3. Each turn calls the Kimi K2.5 model via the Zen API (https://opencode.ai/zen/v1/chat/completions).
  4. The model can invoke tools:
    • google_search — web search via the Tavily API.
    • finish — signals completion and provides the final answer.
  5. Tool results are appended to the conversation and the loop continues.
  6. The loop terminates when finish is called, the turn limit is hit (AGENT_MAX_TURNS, default 20), or the time limit expires (AGENT_MAX_DURATION_SECS, default 120s).

All turns and tool calls are logged. The final answer (if any) and the full log are persisted to the task_runs table.

Environment Variables

Variable Required Default Description
DATABASE_URL PostgreSQL connection string
PORT 3000 HTTP server port
ZEN_API_KEY API key for Zen/Kimi LLM
TAVILY_API_KEY API key for Tavily web search
AUTHENTIK_ISSUER OIDC issuer URL (Authentik)
AUTHENTIK_CLIENT_ID OAuth client ID
AUTHENTIK_CLIENT_SECRET OAuth client secret
CORS_ALLOWED_ORIGINS Comma-separated allowed origins (or mirror)
COOKIE_SECURE false Set true for HTTPS-only cookies
AGENT_MAX_TURNS 20 Max LLM turns per agent run
AGENT_MAX_DURATION_SECS 120 Max wall-clock seconds per agent run

API Routes

All task/run routes require authentication (cookie or Bearer token).

Method Path Description
GET /api/tasks List all tasks with their runs
POST /api/tasks Create a new task
GET /api/tasks/:id Get a single task with runs
PUT /api/tasks/:id Update task goal/cron schedule
POST /api/tasks/:id/runs Trigger a manual re-run
GET /api/runs/recent Latest 50 runs across all tasks
GET /api/auth/session Check current session
GET /api/auth/callback OAuth code → token exchange
POST /api/auth/refresh Refresh access token
POST /api/auth/logout Clear auth cookies

Database Schema

tasksid (UUID PK), goal (text), cron (text, nullable), created_at (timestamptz)

task_runsid (UUID PK), task_id (FK → tasks, cascade delete), status (text), logs (text), answer (text, nullable), created_at (timestamptz)

Migrations are in migration/src/ and run automatically on startup via Migrator::up().

Development

# Backend (from repo root)
cargo run          # requires DATABASE_URL + Authentik vars

# Frontend (from frontend/)
npm install
npm run dev        # Vite dev server on :5173, proxies /api to :3000

# Tests
cargo test

CI / Deployment

The Forgejo Actions pipeline (.forgejo/workflows/pipeline.yaml) triggers on release publish:

  1. Builds the frontend (npm install && npm run build).
  2. Builds the Rust binary (cargo build -r).
  3. Uploads the binary as a release asset.
  4. Deploys to the host: copies binary + frontend dist, restarts the bot systemd user service.