Skip to main content

Agent Overview

Mental Model: Message to Response​

When a user sends a Telegram message, here is exactly what happens:

YOU (Telegram app)
|
| "What tools do you have?"
v
TELEGRAM SERVERS (cloud)
|
| Long-polling (grammy library pulls updates)
v
DOCKER CONTAINER: hollanov
on openclaw-vps-1 (Hostinger VPS, Boston, 76.13.100.227)
|
| src/channels/telegram.ts receives the Update object
| Checks TELEGRAM_ALLOWED_USERS — rejects if not on allowlist
v
AGENT LOOP (src/agent/loop.ts)
|
| 1. Budget check
| BudgetTracker.check() — "do I have tokens/turns left?"
| If no -> stop with "budget exceeded"
|
| 2. Context assembly
| ContextAssembler builds the full prompt:
| - System prompt (personality, tool descriptions, session state)
| - Memory fragments (persistent memories scored by relevance)
| - Conversation history (compacted if getting long)
| - The user's new message
|
| 3. Claude API call
| Anthropic SDK -> api.anthropic.com (HTTPS)
| Sends: system prompt + messages + tool definitions
| Model: claude-sonnet-4-20250514 (configurable via HOLLANOV_MODEL)
v
CLAUDE (Anthropic's servers)
|
| Returns: text response + optional tool_use blocks
v
AGENT LOOP (back on VPS)
|
| 4. Tool execution (if Claude requested tool use)
| a. Permission pipeline — 6 stages:
| deny list -> pre-approved -> read-only auto-approve
| -> destructive detection -> SSH safety -> trust tier
| -> fallback deny
| b. If granted: ToolRegistry.execute()
| shell.ts runs the actual command
| (e.g. `just agent-test`, or `ssh openclaw-vps-1 docker ps`)
| c. Tool result sent back to Claude -> goto step 3 (multi-round)
|
| 5. Final response (no more tool calls)
| a. BudgetTracker.record() — log actual token usage
| b. CostTracker.record() — log dollar cost to ~/.openclaw/cost/
| c. SessionManager.persist() — save to ~/.openclaw/sessions/
| d. SystemLogger.log() — write JSONL to ~/.openclaw/logs/
v
TELEGRAM CHANNEL (src/channels/telegram.ts)
|
| Sends reply via grammy -> Telegram Bot API
v
TELEGRAM SERVERS -> YOUR PHONE
|
"Here are my 32 registered tools: ..."

Key concepts​

  • OpenClaw is the project/repo name. It is not a running service.
  • Hollanov is the custom agent runtime (the TypeScript app in src/agent/). This is what actually runs inside the hollanov Docker container.
  • Ilya is a separate container (openclaw-gateway) running the Hostinger-provided OpenClaw gateway with its own AI. It handles WhatsApp and does not use the Hollanov runtime.
  • The harness is the agent loop + all supporting modules (permissions, budget, memory, sessions, streaming, logging). grammy handles the Telegram protocol; the harness handles everything else.
  • All operations (testing, deployment, VPS management, docs) are initiated through just recipes. Run just --list for the full catalog.

Where it runs​

Everything from "DOCKER CONTAINER" down in the diagram runs on openclaw-vps-1 — a Hostinger KVM 2 VPS in Boston. The Docker container starts via systemd on boot. Secrets are injected by 1Password's op run at startup and never touch disk.

Development environments​

EnvironmentNetworkSecretsVPS AccessSetup
Mac (local)Unrestricted1Password desktop + varlockSSH via 1Password agentjust setup
Claude Code webEgress proxy (needs allowlist config)Project env varsSSH via env var key or generated keyjust setup-web
CI runnerTypically unrestrictedGitHub secrets / env varsSSH via env var keyjust vps-setup-web

For Claude Code web setup details, see Developer Setup — Claude Code Web Environment.

What We Built​

Agent Runtime (src/agent/ — 19 modules + 4 tool modules)​

A complete AI agent engine in TypeScript. Every piece is tested and wired together.

Core pipeline:

  • Tool Registry — 34 tools registered with metadata (name, permissions, risk profile, tags). Query without executing.
  • Permission System — 6-stage pipeline: deny list, pre-approved, read-only auto-approve, destructive detection, SSH safety, trust tiers, fallback deny. Every decision logged.
  • Agent Loop — User message in, budget pre-check, Claude API call, tool execution (with permission gate), stream response, persist session. Handles multi-round tool use automatically.
  • Session Persistence — Full state saved to ~/.openclaw/sessions/ after every turn. Resume where you left off.

Budget and observability:

  • Token Budget — Pre-turn checks halt before spending. Default 500K tokens / 50 turns per session.
  • Event Stream — Typed events: tool_selected, permission_check, message_delta, message_stop with stop reason.
  • System Logger — JSONL at ~/.openclaw/logs/. Categories: init, registry, permission, execution, session, error.
  • Audit Trail — Every permission decision queryable by tool, time, outcome.

Advanced:

  • Workflow Manager — Multi-step operations with checkpoints, idempotency keys, crash recovery.
  • Agent Types — 5 constrained roles (explore, plan, verification, general-purpose, deploy) with allowed/denied tool patterns.
  • Memory System — Persistent + session memory with provenance tracking, relevance scoring (age decay, access frequency, validation recency).
  • Skills — Load from .claude/skills/*/SKILL.md, register as tools.
  • Hooks — Before/after pipeline on tool execution, turns, sessions, permissions.
  • Context Assembly — Provenance-aware fragments with trust levels and token budgets.
  • Compaction — Summarize old messages to manage context size.
  • Doctor — Health checks (Node, gh, op, just, shellcheck).
  • Verification — 5 safety invariants that must always hold.

Tools (src/tools/ — 24 registered)​

CategoryTools
VPSvps-list, vps-add, vps-new, vps-provision, vps-destroy
Docsdocs-build, docs-deploy
Gitpr-create, pr-merge
Qualitylint-sh, lint-md, lint
Agentagent-test, agent-typecheck, agent-doctor, agent-verify
Memorymemory-store, memory-recall
Webweb-search
Skillsskill-coderabbit, skill-deploy, skill-new-doc, skill-status, skill-vps

Channels​

Two AI assistants run on openclaw-vps-1:

NameContainerChannelWhat It Is
HollanovhollanovTelegram @illyarozenovbotOur custom runtime — 34 tools, permissions, memory, sessions
Ilyaopenclaw-gatewayWhatsApp +15089811893Hostinger OpenClaw gateway — default personality

Voice responses: When ELEVENLABS_API_KEY and ELEVENLABS_VOICE_ID are set, Hollanov sends short conversational replies (20-2000 chars, no code blocks/tables) as Telegram voice messages alongside text, using the Ilya Rozenov voice. TTS failures fall back to text-only.

Deployment​

  • Hollanov: just bot-deploy (git pull + rebuild container). Auto-deploys via webhook on push.
  • Ilya: just gateway-start / just gateway-stop
  • Systemd: openclaw-secrets.service starts Hollanov on boot

Tests​

373 tests across 27 files, all passing. Covers every module.

How to Test​

1. Telegram (live, deployed)​

Message @illyarozenovbot on Telegram. Try:

  • "What tools do you have?" — lists all 34 tools
  • "Run the agent tests" — executes just agent-test, reports results
  • "List my VPS instances" — runs vps-list
  • /tools — see all tools with risk indicators
  • /budget — check token usage
  • /reset — start fresh session

2. Local CLI (interactive REPL)​

ANTHROPIC_API_KEY=$(op item get "Anthropic API Key" \
--vault="Shared-Infrastructure" --fields credential --reveal) just agent-run

Then type messages. Commands: /tools, /session, /budget, /quit.

3. Local bot (runs Telegram bot from your Mac)​

just bot-run-op

4. Run tests​

just agent-test        # 373 tests
just agent-verify # 5 safety invariants
just agent-doctor # system health check
just agent-typecheck # TypeScript types

5. Check deployed bot​

just bot-logs          # recent logs
just vps-exec "docker ps" # container status

Project Structure​

src/
agent/
registry.ts permissions.ts session.ts
workflow.ts budget.ts stream.ts
logger.ts audit.ts compaction.ts
context.ts agents.ts memory.ts
skills.ts hooks.ts loop.ts
doctor.ts verify.ts boot.ts
utils.ts
tools/
definitions.ts register.ts shell.ts
channels/
telegram.ts
cli/
agent.ts telegram.ts doctor.ts verify.ts
types/
index.ts
index.ts
deploy/
.env.gateway.tpl start.sh start-gateway.sh
.env.schema Dockerfile docker-compose.yml

All Commands​

CommandWhat It Does
just agent-runStart the interactive agent REPL
just agent-testRun all 373 tests
just agent-verifyVerify 5 safety invariants
just agent-doctorSystem health check
just agent-typecheckTypeScript type checking
just agent-buildCompile TypeScript to dist/
just bot-runRun Telegram bot locally
just bot-run-opRun Telegram bot locally with 1Password secrets
just bot-deployDeploy bot to VPS (git pull + rebuild)