-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconfig.example.yaml
More file actions
354 lines (319 loc) · 22.8 KB
/
Copy pathconfig.example.yaml
File metadata and controls
354 lines (319 loc) · 22.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
# AIr-Friends Configuration
# Copy this file to config.yaml and customize as needed.
# Use ${ENV_VAR} placeholders where appropriate (see src/utils/env.ts for supported mappings).
# Logging configuration
logging:
level: "INFO" # Valid: DEBUG, INFO, WARN, ERROR, FATAL (default: INFO)
# GELF (Graylog Extended Log Format) output configuration
# When enabled, log messages are also sent to a GELF-compatible log server via HTTP
gelf:
enabled: false # Enable GELF log output (default: false)
endpoint: "" # GELF endpoint URL (e.g., "http://graylog.example.com:12202/gelf")
hostname: "air-friends" # Source hostname in GELF messages (default: "air-friends")
protocol: "http" # Transport protocol: "http", "tcp", or "udp" (default: "http")
# compress: true # GZIP compression for UDP transport (default: true when protocol is "udp")
# Platform configurations
platforms:
discord:
enabled: true # true/false (default: false); override with env DISCORD_ENABLED
token: "${DISCORD_TOKEN}" # Bot token; use environment variable DISCORD_TOKEN or set here
guildIds: [] # List of guild IDs to operate in (empty = all)
allowDm: true # Respond to direct messages (default: true)
respondToMention: true # Respond when mentioned (default: true)
commandPrefix: "!" # Optional command prefix (set empty to disable)
# Spontaneous posting: agent posts messages on its own schedule
spontaneousPost:
enabled: false # Enable spontaneous posting (default: false)
minIntervalMs: 10800000 # Minimum interval: 3 hours (default)
maxIntervalMs: 43200000 # Maximum interval: 12 hours (default)
contextFetchProbability: 0.5 # Probability of including recent messages (0.0-1.0, default: 0.5)
# Typing indicator: show "typing..." in Discord while processing
typingIndicator:
enabled: false # Show typing indicator during ACP sessions (default: false, security consideration)
# Channel lurk reply: periodically check whitelisted channels and auto-reply
channelLurk:
enabled: false # Enable channel lurk reply (default: false)
intervalMs: 1800000 # Check interval: 30 minutes (default)
misskey:
enabled: false # true/false (default: false); override with env MISSKEY_ENABLED
host: "${MISSKEY_HOST}" # e.g., misskey.example.com - or set via MISSKEY_HOST env var
token: "${MISSKEY_TOKEN}" # API token (preferred via MISSKEY_TOKEN env var)
secure: true # Use wss/https when connecting (true/false, default: true)
respondToMention: true # Respond to mentions (default: true)
allowDm: true # Respond to DMs (default: true)
# Spontaneous posting: agent posts notes on its own schedule
spontaneousPost:
enabled: false # Enable spontaneous posting (default: false)
minIntervalMs: 10800000 # Minimum interval: 3 hours (default)
maxIntervalMs: 43200000 # Maximum interval: 12 hours (default)
contextFetchProbability: 0.5 # Probability of including recent messages (0.0-1.0, default: 0.5)
# Agent/LLM configuration
agent:
model: "openrouter/deepseek/deepseek-v4-pro" # Model identifier (OpenCode provider/model)
systemPromptPath: "./prompts/system_reply.md" # Path to the system prompt file
tokenLimit: 20000 # Max tokens for context
geminiApiKey: "${GEMINI_API_KEY}" # Optional OpenCode Gemini provider API key (env: GEMINI_API_KEY)
opencodeApiKey: "${OPENCODE_API_KEY}" # Optional OpenCode API key (env: OPENCODE_API_KEY)
openRouterApiKey: "${OPENROUTER_API_KEY}" # Optional OpenRouter API key (env: OPENROUTER_API_KEY)
defaultAgentType: "${AGENT_DEFAULT_TYPE}" # Default ACP agent: "opencode" (env: AGENT_DEFAULT_TYPE)
skillsDir: "skills" # Path to skills directory (default: "skills"); use "/home/deno/.agents/skills" for container deployment; override with env AGENT_SKILLS_DIR
# Reasoning effort (ACP thought_level): controls how hard the model "thinks".
# Global default; resolved per session as: routing rule -> section -> this global value.
# Values: "none" | "low" | "medium" | "high", or "default" = do not configure
# (let the agent/model decide). Agent-specific tokens are passed through as-is.
# Best-effort: if the agent/model does not expose a thought_level option, it is a no-op.
# Override the global with env AGENT_REASONING_EFFORT.
reasoningEffort: "default"
# Bootstrap OpenCode version check (observability only, never blocks startup):
# the system warns when the installed opencode CLI reports a version below the
# known-good minimum (default 1.17.13, the first release with the enriched ACP
# permission request shape). Override the minimum with env AGENT_OPENCODE_MIN_VERSION.
# This only affects the bootstrap WARN marker (OK/BELOW_MINIMUM/UNKNOWN) — it is
# NOT a functional gate. The container image pins the version via
# Containerfile OPENCODE_VERSION + per-arch SHA-256 checksums.
# External skills to install at startup (optional)
# Each entry specifies a GitHub repo and skill name to install via `npx --yes --package=skills skills add`
# externalSkills:
# - repo: "jim60105/copilot-prompt"
# skill: "create-blog-post"
# Skill Auto-Approve List: skills that are automatically approved in restricted (non-YOLO) mode.
# Each entry is a skill name. When empty or not set, falls back to scanning the built-in skills directory.
# Override with env AGENT_AUTO_APPROVE_SKILLS (comma-separated).
# autoApproveSkills:
# - "memory-save"
# - "memory-search"
# - "memory-patch"
# - "memory-stats"
# - "memory-export"
# - "fetch-context"
# - "send-reply"
# - "edit-reply"
# - "send-file"
# - "react-message"
# - "set-reminder"
# - "list-reminders"
# - "cancel-reminder"
# - "self-research"
# - "agent-browser"
# # External skills can also be listed here:
# # - "create-blog-post"
# Model routing: per-user/per-context model selection
# When enabled, rules are evaluated in order (first-match wins).
# All conditions in a rule's match are AND-combined; contentKeywords entries are OR-combined.
# If no rule matches, falls back to agent.model (or selfResearch.model / memoryMaintenance.model for those session types).
#
# Each rule MAY also set `reasoningEffort` to control thinking effort per context.
# The FIRST matching rule wins; if that rule omits `reasoningEffort`, resolution falls back
# to the section value (selfResearch/memoryMaintenance/conversationSummary) then agent.reasoningEffort.
# A rule can set `model` and `reasoningEffort` independently (one without the other).
modelRouting:
enabled: false
rules: []
# Example rules:
# # Specific account + research keywords → research model at high effort
# - match:
# channel: "discord/account/12345678901234567"
# contentKeywords: ["研究", "research"]
# model: "openrouter/google/gemini-2.5-pro"
# reasoningEffort: "high"
# # Any message with research keywords → research model
# - match:
# contentKeywords: ["研究", "research", "論文", "paper"]
# model: "openrouter/google/gemini-2.5-pro"
# # Specific account (any content) → premium model
# - match: { channel: "discord/account/12345678901234567" }
# model: "openrouter/deepseek/deepseek-v3.2"
# # Spontaneous posts can think less to save cost (model unchanged, effort lowered)
# - match: { sessionType: "spontaneous" }
# reasoningEffort: "low"
# External MCP Servers: register MCP-compatible servers for the Agent to use.
# The Agent connects to these servers during session creation and can call their tools.
# All Agents support stdio transport. HTTP/SSE support depends on the Agent's capabilities.
# Values support ${ENV_VAR} syntax for environment variable expansion.
# Override with env AGENT_MCP_SERVERS (JSON string).
mcpServers: []
# Example configurations:
# # Stdio transport (default) — spawns a subprocess
# - name: "github"
# command: "npx"
# args: ["-y", "@modelcontextprotocol/server-github"]
# env:
# GITHUB_TOKEN: "${GITHUB_TOKEN}"
#
# # HTTP transport — connects to a running server
# - name: "database"
# transport: "http"
# url: "http://localhost:3002/mcp"
# headers:
# Authorization: "Bearer ${API_TOKEN}"
#
# # SSE transport (deprecated) — connects to an SSE endpoint
# - name: "events"
# transport: "sse"
# url: "https://events.example.com/mcp"
# Dry run / debug mode: assemble context without calling Agent
# Useful for prompt engineering, CI/CD smoke tests, and context debugging
dryRun:
enabled: false # Enable dry run mode (default: false); override with env DRY_RUN_ENABLED
outputPath: "./data/dry-run/" # Output directory for assembled prompts; override with env DRY_RUN_OUTPUT_PATH
mockReply: "(Dry run 模式 — 此為測試回覆)" # Mock reply text (empty = no reply); override with env DRY_RUN_MOCK_REPLY
# Sandbox settings for agent subprocess isolation
# sandbox:
# filterEnv: true # Filter subprocess environment variables (default: true); override with env AGENT_SANDBOX_FILTER_ENV
# networkIsolation: false # Full Linux network namespace isolation (default: false). NOTE: full isolation gives the agent an EMPTY network namespace, which also severs its loopback access to the Skill API. Prefer egressProxy below. Override with env AGENT_SANDBOX_NETWORK_ISOLATION
# allowedEnvVars: [] # Additional env var names to allow through the filter; override with env AGENT_SANDBOX_ALLOWED_ENV_VARS (comma-separated)
# allowedWriteExtensions: [".md", ".txt"] # Allowed file extensions for agent workspace writes in restricted mode; override with env AGENT_SANDBOX_ALLOWED_WRITE_EXTENSIONS (comma-separated)
# filesystemConfinement: false # F12 D4: OPT-IN (default false). Confine the agent's filesystem view via bubblewrap so the daemon's /proc/1/environ and other users' workspaces are unreadable regardless of the permission layer. Mounts a fresh /proc, which is NOT possible inside a doubly-nested user namespace (e.g. rootless podman) — verify with scripts/probe-sandbox-caps.sh on your real runtime before enabling. FAILS CLOSED at spawn when enabled but unavailable. Override with env AGENT_SANDBOX_FILESYSTEM_CONFINEMENT
# egressProxy: true # F14: mediate agent egress (webfetch/websearch/agent-browser) through a local validating proxy that blocks loopback/private/link-local/metadata targets while allowing public destinations (default: true). Override with env AGENT_SANDBOX_EGRESS_PROXY
# egressProxyPort: 0 # Port for the validating egress proxy (0 = ephemeral); override with env AGENT_SANDBOX_EGRESS_PROXY_PORT
# unrestrictedEgress: false # Explicit opt-in to UNMEDIATED agent egress for trusted single-tenant deployments that accept the SSRF risk (default: false). When neither egressProxy nor this is set, the agent fails closed rather than getting open egress. Override with env AGENT_SANDBOX_UNRESTRICTED_EGRESS
# egressAllowHosts: [] # Operator-trusted egress destinations exempt from the proxy's disallowed-range rejection (default: []). Bare hostnames or literal IPs only — no scheme/port/path; matching is exact, never a range. Entries are operator-audited trust grants: prefer literal IPs or cluster-internal service names; a loopback entry exposes ALL loopback ports (dashboard, Skill API), not just one service. Cloud-metadata addresses stay blocked regardless. Also appended to the agent's NO_PROXY. Override with env AGENT_SANDBOX_EGRESS_ALLOW_HOSTS (comma-separated), e.g. "192.168.1.10,internal-proxy"
# Idle timeout detection for ACP connections
# Detects silently disconnected Agent connections and attempts recovery
idleTimeout:
enabled: true # Enable idle timeout detection (default: true); override with env AGENT_IDLE_TIMEOUT_ENABLED
timeoutMs: 300000 # Idle timeout in ms (default: 300000 = 5 minutes); override with env AGENT_IDLE_TIMEOUT_MS
checkIntervalMs: 30000 # Check interval in ms (default: 30000 = 30 seconds); override with env AGENT_IDLE_TIMEOUT_CHECK_INTERVAL_MS
# Maximum time to wait for the ACP handshake (connection.initialize()) during connect().
# A crashed or hung agent subprocess fails connect() fast instead of hanging forever.
connectTimeoutMs: 30000 # Connect handshake timeout in ms (default: 30000 = 30 seconds); override with env AGENT_CONNECT_TIMEOUT_MS
# Git credential store for agent subprocesses (effective only in YOLO mode)
# Configures git credential.helper = store at startup so the agent can use
# git push/pull/clone without exposing PATs in environment variables or prompts.
# Credentials are shared from gitBackup.authUser/authPassword (or GITHUB_TOKEN).
# gitCredential:
# enabled: false
# # host: "github.com" # Override host (default: from gitBackup.remoteUrl)
# Memory system configuration
memory:
searchLimit: 10 # Max number of search results (default: 10)
maxChars: 2000 # Max characters stored per memory (default: 2000)
recentMessageLimit: 20 # Number of recent messages included in context (default: 20)
workingTierLimit: 20 # Max working-tier memories before auto-demotion to archive (default: 20); override with env MEMORY_WORKING_TIER_LIMIT
# Channel-scoped memory write policy (F15):
# "sessions" (default) — ordinary channel sessions may write channel memory
# (entries are attributed, non-durable/decaying, bounded, and moderatable
# via the dashboard Channel Memory tab).
# "curated" — user-driven channel writes are rejected; durable channel
# knowledge comes only from an operator/curated flow.
channelWritePolicy: sessions
# Conversation summary - auto-generate summaries after each session
conversationSummary:
enabled: true # Enable post-session conversation summaries (default: true); override with env CONVERSATION_SUMMARY_ENABLED
model: "" # Model for summary generation (defaults to agent.model); override with env CONVERSATION_SUMMARY_MODEL
# reasoningEffort: "low" # Reasoning effort for summaries (falls back to agent.reasoningEffort when omitted)
# Workspace configuration
workspace:
repoPath: "./data" # Root path for workspace data (default: ./data)
workspacesDir: "workspaces" # Directory name under repoPath (default: workspaces)
# Agent global workspace is auto-created at {repoPath}/agent-workspace/
# This directory is managed by the agent for long-term knowledge notes
# Skill API (used by external shell-based skills)
skillApi:
enabled: true # Enable skill API server for shell-based skills (default: true)
host: "127.0.0.1" # Host to bind (should be localhost)
port: 3001 # Port for skill API server (default: 3001)
# Health check configuration (optional)
health:
enabled: true # Enable HTTP health check endpoint (default: true)
port: 8080 # Port for health check (default: 8080)
# Prometheus metrics endpoint (shared with health check server port)
metrics:
enabled: false # Enable Prometheus metrics (default: false); override with env METRICS_ENABLED
path: "/metrics" # Metrics endpoint path (default: "/metrics"); override with env METRICS_PATH
# Reply policy: "all" | "public" | "channels"
# - all: Reply to everyone
# - public: Reply in public channels + enabled DM channels
# - channels: Only reply to configured channels (default)
replyPolicy: "channels" # override with env REPLY_POLICY (REPLY_TO also accepted as alias)
# Channel configurations
# Each entry defines a channel with individual feature toggles
channels:
# Discord account (DM)
- id: "discord/account/560842157351763989"
enabled: true
spontaneousPost: false
rateLimitBypass: true
yolo: true # Run Agent in YOLO mode for this account
# Discord channel
- id: "discord/channel/873618490202931231"
enabled: true
spontaneousPost: true
channelLurk: true
yolo: false # Default: restricted mode
# Misskey account (DM)
- id: "misskey/account/agy61oh08uzl000g"
enabled: true
spontaneousPost: false
# Misskey timeline (bot own timeline)
# - id: "misskey/timeline/self"
# spontaneousPost: true
# Self-research: agent periodically reads RSS and researches topics
selfResearch:
enabled: false # Enable self-research (default: false); override with env SELF_RESEARCH_ENABLED
model: "gpt-5-mini" # Model for research (separate from chat); override with env SELF_RESEARCH_MODEL
# reasoningEffort: "high" # Reasoning effort for research (falls back to agent.reasoningEffort when omitted)
rssFeeds: # RSS feed sources; override with env SELF_RESEARCH_RSS_FEEDS (JSON string)
- url: "https://example.com/feed.xml"
name: "Tech News"
- url: "https://example.org/rss"
minIntervalMs: 43200000 # Minimum interval: 12 hours (default); override with env SELF_RESEARCH_MIN_INTERVAL_MS
maxIntervalMs: 86400000 # Maximum interval: 24 hours (default); override with env SELF_RESEARCH_MAX_INTERVAL_MS
# Memory maintenance: agent periodically summarizes and compacts old memories
memoryMaintenance:
enabled: false # Enable memory maintenance (default: false); override with env MEMORY_MAINTENANCE_ENABLED
model: "gpt-5-mini" # Model for maintenance (separate from chat); override with env MEMORY_MAINTENANCE_MODEL
# reasoningEffort: "low" # Reasoning effort for maintenance (falls back to agent.reasoningEffort when omitted)
minMemoryCount: 50 # Minimum enabled memories required to run; override with env MEMORY_MAINTENANCE_MIN_MEMORY_COUNT
intervalMs: 604800000 # Fixed interval: 7 days (default); override with env MEMORY_MAINTENANCE_INTERVAL_MS
# Rate limiting - prevent excessive API usage per user
# Complements accessControl: accessControl decides "who can", rateLimit decides "how often"
rateLimit:
enabled: false # Enable rate limiting (default: false); override with env RATE_LIMIT_ENABLED
maxRequestsPerWindow: 10 # Max requests per user per sliding window; override with env RATE_LIMIT_MAX_REQUESTS_PER_WINDOW
windowMs: 600000 # Sliding window duration in ms (default: 10 min); override with env RATE_LIMIT_WINDOW_MS
cooldownMs: 600000 # Cooldown period after limit exceeded in ms (default: 10 min); override with env RATE_LIMIT_COOLDOWN_MS
# Session audit log - per-session JSONL audit trail for replay and debugging
audit:
enabled: false # Enable audit logging (default: false); override with env AUDIT_ENABLED
retentionDays: 7 # Log retention in days (default: 7); override with env AUDIT_RETENTION_DAYS
hashContent: true # SHA-256 hash user content (default: true); override with env AUDIT_HASH_CONTENT
includedPhases: # Only record specified phases, empty = all; override with env AUDIT_INCLUDED_PHASES (comma-separated)
- "trigger_received"
- "skill_call"
- "reply_sent"
- "session_end"
# Git backup - backs up the entire data/ directory to a remote Git repository
gitBackup:
enabled: false # Enable Git backup (default: false); override with env GIT_BACKUP_ENABLED
remoteUrl: "" # Remote Git repository URL (HTTPS); override with env GIT_BACKUP_REMOTE_URL
intervalMs: 3600000 # Backup interval in ms (default: 1 hour); override with env GIT_BACKUP_INTERVAL_MS
authorName: "AIr-Friends Backup" # Git author name; override with env GIT_BACKUP_AUTHOR_NAME
authorEmail: "airfriends-backup@noreply.github.com" # Git author email; override with env GIT_BACKUP_AUTHOR_EMAIL
authUser: "" # HTTPS auth username (default: authorEmail → "x-access-token"); override with env GIT_BACKUP_AUTH_USER
authPassword: "" # HTTPS auth password/token (default: GITHUB_TOKEN env); override with env GIT_BACKUP_AUTH_PASSWORD
# Scheduled reminders - allows the agent to set future reminders for users
# Reminders can only be set in DM conversations, and are always delivered via DM
reminders:
enabled: false # Enable scheduled reminders (default: false); override with env REMINDERS_ENABLED
maxRemindersPerUser: 20 # Max active reminders per user (default: 20); override with env REMINDERS_MAX_PER_USER
minIntervalMs: 60000 # Minimum reminder delay from now in ms (default: 1 minute); override with env REMINDERS_MIN_INTERVAL_MS
persistPath: "reminders.jsonl" # File name for reminder data within workspace (default: reminders.jsonl); override with env REMINDERS_PERSIST_PATH
checkIntervalMs: 30000 # How often to check for due reminders in ms (default: 30 seconds); override with env REMINDERS_CHECK_INTERVAL_MS
# ─── Skills Configuration ─────────────────────────────
skills:
sendFile:
enabled: false # Enable send-file skill (default: false, disabled for security); override with env SKILL_SEND_FILE_ENABLED
maxFileSizeMb: 25 # File size limit in MB, 0 = use platform default; override with env SKILL_SEND_FILE_MAX_SIZE_MB
allowedExtensions: [] # Allowed file extension whitelist, empty = no restriction; override with env SKILL_SEND_FILE_ALLOWED_EXTENSIONS
# Example: [".png", ".jpg", ".gif", ".pdf", ".txt", ".md"]
maxFilesPerInvocation: 10 # Max files per send-file invocation (default: 10, Discord attachment cap); override with env SKILL_SEND_FILE_MAX_FILES_PER_INVOCATION
maxTotalSizeMb: 50 # Max aggregate file size per invocation in MB (default: 50); override with env SKILL_SEND_FILE_MAX_TOTAL_SIZE_MB
# ─── Web Dashboard ─────────────────────────────────────
dashboard:
enabled: false # Enable web dashboard (default: false); override with env DASHBOARD_ENABLED
port: 8090 # Dashboard HTTP port (default: 8090); override with env DASHBOARD_PORT
host: "127.0.0.1" # Bind host (default: 127.0.0.1). Set to "0.0.0.0" to expose on all interfaces; override with env DASHBOARD_HOST
passphrase: "" # Login passphrase (required when enabled, min 16 chars); override with env DASHBOARD_PASSPHRASE
behindHttpsProxy: false # Set true when served behind an HTTPS-terminating reverse proxy; enables the Secure cookie flag. NOT derived from X-Forwarded-Proto. Override with env DASHBOARD_BEHIND_HTTPS_PROXY
trustedProxies: [] # Real connection addresses whose X-Forwarded-For is trusted for login rate-limit keying (default: empty = ignore XFF). Override with env DASHBOARD_TRUSTED_PROXIES (comma-separated)