A trust and safety agent that interacts with Osprey for investigation, real-time analysis, and prevention implementations
1# Phoebe
2
3Phoebe is an AI-powered trust and safety agent for the [AT Protocol](https://atproto.com/) network. It automates safety operations by analyzing network threats and creating rules to detect and resolve emerging issues. Phoebe uses three different services to achieve this:
4
5- **[Osprey](https://github.com/roostorg/osprey)** - Real-time rules engine for threat detection
6- **[Ozone](https://github.com/bluesky-social/ozone)** - Moderation service for labeling and takedowns
7- **[ClickHouse](https://clickhouse.com/)** - Event analytics database for pattern discovery, which is populated by Osprey
8
9This allows it to:
10
11- **Rule Management** - Write, validate, and deploy rules for Osprey
12- **Data Analysis** - Query ClickHouse to analyze what is happening on your network
13- **Investigation** - Look up domains, IPs, URLs, and WHOIS records to investigate threats
14- **Content Detection** - Find similar posts to detect coordinated spam and templated abuse
15- **Moderation** - Apply labels and take moderation actions via Ozone (not actually implemented yet...)
16
17## How It Works
18
19Phoebe uses a model API as its reasoning backer. The agent writes and executes Typescript code in a sandboxed Deno runtime to interact with its tools — querying event data, creating safety rules, and managing moderation actions.
20
21```
22┌─────────────────────────────────────────────────────────┐
23│ Model API │
24├─────────────────────────────────────────────────────────┤
25│ Tool Execution (Deno Sandbox) │
26├──────────┬───────────┬──────────────┬───────────────────┤
27│ Osprey │ ClickHouse│ Ozone │ Investigation │
28│ (Rules) │ (Queries) │ (Moderation) │ (Domain/IP/WHOIS) │
29└──────────┴───────────┴──────────────┴───────────────────┘
30```
31
32#### Why not traditional tool calling?
33
34See [Cloudflare's blog post](https://blog.cloudflare.com/code-mode/) on this topic.
35
36One of the largest benefits of letting the agent write and execute its own code is that it allows for tool chaining and grouping. Traditionally, each subsequent tool call results in a round trip for _each_ tool call. When the agent can write its own code, it can instead
37chain these calls together. For example, if the agent knows it wants to grab the results of _three separate_ SQL queries, it can group all three of those calls in a single `execute_code` block and receive the context.
38
39When executing code inside of Deno, Deno is ran with the bare minimum of permissions. For example, it cannot access the file system, the network (local or remote), or use NPM packages. Both execution time and memory limits are applied. All network requests are done in Python,
40in code that _you_ write, not the agent.
41
42| Limit | Value |
43|-------|-------|
44| Max code size | 50,000 characters |
45| Max tool calls per execution | 25 |
46| Max output size | 1 MB |
47| Execution timeout | 60 seconds |
48| V8 heap memory | 256 MB |
49
50## Tools
51
52Phoebe has access to the following tools, organized by namespace:
53
54| Namespace | Tool | Description |
55|-----------|------|-------------|
56| `clickhouse` | `query(sql)` | Execute SQL queries against Clickhouse |
57| `clickhouse` | `getSchema()` | Get the table schema and column info |
58| `osprey` | `getConfig()` | Get available features, labels, rules, and actions |
59| `osprey` | `getUdfs()` | Get available UDFs for rule writing |
60| `osprey` | `listRuleFiles(directory?)` | List existing `.sml` rule files |
61| `osprey` | `readRuleFile(file_path)` | Read an existing rule file |
62| `osprey` | `saveRule(file_path, content)` | Save or create a rule file |
63| `osprey` | `validateRules()` | Validate the ruleset |
64| `content` | `similarity(text, threshold?, limit?)` | Find similar posts using n-gram distance |
65| `domain` | `checkDomain(domain)` | DNS lookups and HTTP status checks |
66| `ip` | `lookup(ip)` | GeoIP and ASN lookups |
67| `url` | `expand(url)` | Follow redirect chains and detect shorteners |
68| `whois` | `lookup(domain)` | Domain registration and WHOIS info |
69| `ozone` | `applyLabel(subject, label)` | Apply a moderation label (not yet implemented) |
70| `ozone` | `removeLabel(subject, label)` | Remove a moderation label (not yet implemented) |
71
72## Prerequisites
73
74- [Deno](https://deno.com/) runtime
75- [uv](https://github.com/astral-sh/uv) package manager
76
77## Installation
78
79```bash
80git clone https://github.com/haileyok/osprey-agent.git
81cd osprey-agent
82uv sync --frozen
83```
84
85## Configuration
86
87Create a `.env` file in the project root:
88
89```env
90# Required
91MODEL_API_KEY="sk-ant-api03-..."
92MODEL_NAME="claude-sonnet-4-5-20250929"
93
94# Optional - Model API backend (default: anthropic)
95# MODEL_API="anthropic" # or "openai", "openapi"
96# MODEL_ENDPOINT="" # required for openapi, ie https://api.moonshot.ai/v1/completions
97
98# Osprey
99OSPREY_BASE_URL="http://localhost:5004"
100OSPREY_REPO_URL="https://github.com/roostorg/osprey"
101OSPREY_RULESET_URL="https://github.com/your-org/your-ruleset"
102
103# ClickHouse
104CLICKHOUSE_HOST="localhost"
105CLICKHOUSE_PORT=8123
106CLICKHOUSE_DATABASE="default"
107CLICKHOUSE_USER="default"
108CLICKHOUSE_PASSWORD="clickhouse"
109```
110
111All settings can also be passed as CLI flags (see `--help`).
112
113## Usage
114
115### Interactive Chat
116
117Start a conversation with Phoebe to investigate threats and create rules:
118
119```bash
120uv run main.py chat
121```
122
123### CLI Options
124
125Both commands accept overrides for any config value:
126
127```bash
128uv run main.py chat \
129 --clickhouse-host localhost \
130 --clickhouse-port 8123 \
131 --osprey-base-url http://localhost:5004 \
132 --model-api-key $ANTHROPIC_API_KEY
133```