Skip to content

Commit f39883f

Browse files
committed
Add integration tests for auto-orchestration, profile reflection, and scheduler
- Implement integration tests for auto-orchestration in natural language turns, ensuring orchestrator functionality when enabled and fallback to agent loop when disabled. - Create tests for user profile prompt injection and learned-skill reflection, verifying the correct handling of user profiles and skill materialization. - Introduce tests for the reusable scheduler tick executor, validating the execution of scheduled tasks, task state management, and interaction with active sessions. - Document the implementation plan for the second phase of the Alice agent evolution, outlining tasks for runtime-state persistence, identity binding, background scheduling, and multi-ACP orchestration.
1 parent 3b9e9f5 commit f39883f

48 files changed

Lines changed: 5798 additions & 219 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@
99

1010
A configurable AI agent application with pluggable backends, built with hexagonal architecture on top of the [Bob](https://github.com/longcipher/bob) framework.
1111

12+
Alice combines short-term turn memory with two longer-lived learning layers:
13+
14+
- User profiles: Alice distills durable user preferences and project context into a profile that is injected into future turns.
15+
- Learned skills: when reflection is enabled, Alice can synthesize reusable `SKILL.md` files from successful sessions and save them into a configured skills directory.
16+
- Global identity bindings: CLI, Telegram, and Discord users can be linked to one global user id so active sessions survive channel switches.
17+
- Scheduled tasks: Alice can persist recurring background prompts in SQLite, execute them from a Tokio scheduler loop, and push results back into the active bound channel thread when available.
18+
1219
## Architecture
1320

1421
```text
@@ -82,6 +89,15 @@ cargo run -p alice-cli -- --config alice.toml chat
8289
# Run one prompt and exit
8390
cargo run -p alice-cli -- --config alice.toml run "summarize our current memory setup"
8491

92+
# Issue a bind token for a global user id
93+
cargo run -p alice-cli -- --config alice.toml bind-token alice-user-1 --provider telegram
94+
95+
# Create a background scheduled task
96+
cargo run -p alice-cli -- --config alice.toml schedule add \
97+
--global-user-id alice-user-1 \
98+
--prompt "summarize recent alerts" \
99+
--every-minutes 60
100+
85101
# Run with multi-channel support
86102
cargo run -p alice-cli -- --config alice.toml channel
87103
```
@@ -104,6 +120,14 @@ bm25_weight = 0.3
104120
vector_weight = 0.7
105121
vector_dimensions = 384
106122
enable_vector = true
123+
124+
[reflection]
125+
enabled = false
126+
learned_skills_dir = "./skills/learned"
127+
128+
[scheduler]
129+
enabled = false
130+
poll_interval_ms = 30000
107131
```
108132

109133
### Agent Backend
@@ -122,6 +146,22 @@ backend = "acp"
122146
acp_command = "opencode"
123147
acp_args = ["serve", "--acp"]
124148
acp_working_dir = "/path/to/project"
149+
150+
# Multi-profile ACP orchestration
151+
[agent]
152+
backend = "acp"
153+
auto_orchestrate = true
154+
primary_profile = "manager"
155+
156+
[agent.acp_profiles.manager]
157+
command = "opencode"
158+
args = ["serve", "--acp"]
159+
working_dir = "/path/to/project"
160+
161+
[agent.acp_profiles.writer]
162+
command = "codex"
163+
args = ["--acp"]
164+
working_dir = "/path/to/project"
125165
```
126166

127167
Build with ACP support:
@@ -145,6 +185,41 @@ path = "./skills"
145185
recursive = true
146186
```
147187

188+
When `[reflection]` is enabled, point `learned_skills_dir` under one of your configured skill source roots, for example `./skills/learned`. Alice reloads skill sources on each turn, so reflected skills can be selected without restarting the process.
189+
190+
### Long-Term Profiles
191+
192+
Alice stores long-lived user profiles alongside the memory index in SQLite. These profiles are updated from durable self-descriptions in user turns, such as preferences, project constraints, and repository context, then injected into future prompts as "Known user profile" context.
193+
194+
### Global Identity Binding
195+
196+
Use `--global-user-id` on CLI `run` or `chat` sessions to anchor them to a stable user identity:
197+
198+
```bash
199+
cargo run -p alice-cli -- --config alice.toml chat --global-user-id alice-user-1
200+
```
201+
202+
Then issue a bind token and consume it from Telegram or Discord with `/bind <token>`:
203+
204+
```bash
205+
cargo run -p alice-cli -- --config alice.toml bind-token alice-user-1 --provider telegram
206+
```
207+
208+
Once a channel identity is bound, Alice reuses the latest active session lease for that global user whenever possible.
209+
For long-running channel sessions, Alice also records the active thread id so background scheduler results can be posted back to the same Telegram or Discord conversation.
210+
211+
### Learned Skill Reflection
212+
213+
Enable post-turn reflection to have Alice run a hidden reflection pass after successful responses:
214+
215+
```toml
216+
[reflection]
217+
enabled = true
218+
learned_skills_dir = "./skills/learned"
219+
```
220+
221+
The reflector writes learned workflows as `./skills/learned/<skill-name>/SKILL.md`. If a turn does not teach a reusable workflow, nothing is written.
222+
148223
### Telegram
149224

150225
Alice supports Telegram as a chat channel via the `teloxide` crate.
@@ -182,6 +257,8 @@ cargo run -p alice-cli --features telegram -- --config alice.toml channel
182257

183258
Messages sent to your bot will be processed by Alice and responses sent back. Each chat creates a unique session for memory continuity.
184259

260+
To link a Telegram account to an existing CLI identity, issue a bind token from the CLI and send `/bind <token>` to the bot.
261+
185262
### Discord
186263

187264
```toml
@@ -207,6 +284,51 @@ args = ["-y", "@modelcontextprotocol/server-filesystem", "."]
207284
tool_timeout_ms = 15000
208285
```
209286

287+
### Scheduler
288+
289+
Enable the background scheduler loop in long-running `chat` or `channel` sessions:
290+
291+
```toml
292+
[scheduler]
293+
enabled = true
294+
poll_interval_ms = 30000
295+
```
296+
297+
Create and inspect scheduled tasks from the CLI:
298+
299+
```bash
300+
# Every 30 minutes
301+
cargo run -p alice-cli -- --config alice.toml schedule add \
302+
--global-user-id alice-user-1 \
303+
--prompt "summarize pending PR reviews" \
304+
--every-minutes 30
305+
306+
# Daily at 08:15
307+
cargo run -p alice-cli -- --config alice.toml schedule add \
308+
--global-user-id alice-user-1 \
309+
--prompt "prepare the morning project brief" \
310+
--daily-hour 8 \
311+
--daily-minute 15
312+
313+
cargo run -p alice-cli -- --config alice.toml schedule list
314+
```
315+
316+
Scheduled tasks execute through the normal memory-aware turn pipeline. When the owning global user has an active bound channel/thread lease and that channel adapter is live, Alice posts the task result back into that same thread.
317+
318+
### ACP Orchestration
319+
320+
When multiple ACP profiles are configured, you can run an explicit manager/worker orchestration flow:
321+
322+
```bash
323+
cargo run -p alice-cli --features acp-agent -- --config alice.toml orchestrate \
324+
--session-id multi-agent-run \
325+
--manager-prompt "Plan how to refactor the auth subsystem." \
326+
--worker planner "Outline the migration steps." \
327+
--worker writer "Draft the concrete code changes."
328+
```
329+
330+
If `agent.auto_orchestrate = true`, ordinary natural-language chat turns also fan out through the configured non-primary ACP profiles and return the aggregated orchestration summary to the user.
331+
210332
## Example: Using OpenCode as an ACP Agent
211333

212334
[OpenCode](https://opencode.ai) is a terminal-based AI coding agent that supports ACP mode.

alice.toml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,25 @@ dispatch_mode = "native_preferred"
77
# Agent backend selection: "bob" (default) or "acp" (requires --features acp-agent).
88
# [agent]
99
# backend = "bob"
10+
# auto_orchestrate = false
1011
# acp_command = "claude-agent-acp"
1112
# acp_args = []
1213
# acp_working_dir = "."
14+
#
15+
# # Optional named ACP profiles for orchestration
16+
# # Set auto_orchestrate = true to fan out ordinary natural-language turns
17+
# # across all non-primary ACP profiles.
18+
# primary_profile = "manager"
19+
#
20+
# [agent.acp_profiles.manager]
21+
# command = "opencode"
22+
# args = ["serve", "--acp"]
23+
# working_dir = "."
24+
#
25+
# [agent.acp_profiles.writer]
26+
# command = "codex"
27+
# args = ["--acp"]
28+
# working_dir = "."
1329

1430
[memory]
1531
db_path = "./.alice/memory.db"
@@ -19,6 +35,10 @@ vector_weight = 0.7
1935
vector_dimensions = 384
2036
enable_vector = true
2137

38+
# Alice now keeps lightweight long-term user profiles in the same memory DB.
39+
# Profiles are refreshed automatically from durable self-descriptions such as
40+
# preferences, project context, and workflow constraints.
41+
2242
# Skill system configuration — auto-selects relevant SKILL.md files per turn.
2343
# [skills]
2444
# enabled = true
@@ -29,6 +49,14 @@ enable_vector = true
2949
# path = "./skills"
3050
# recursive = true
3151

52+
# Optional post-turn reflection. When enabled, Alice asks a hidden reflector
53+
# to turn reusable workflows into learned `SKILL.md` files under the directory
54+
# below. Point the directory under one of your configured skill sources so the
55+
# learned skills are eligible for future turns.
56+
# [reflection]
57+
# enabled = true
58+
# learned_skills_dir = "./skills/learned"
59+
3260
# Channel adapters — enable multi-channel input beyond the default CLI REPL.
3361
# Discord requires ALICE_DISCORD_TOKEN env var.
3462
# Telegram requires ALICE_TELEGRAM_TOKEN env var.
@@ -37,6 +65,13 @@ enable_vector = true
3765
# [channels.telegram]
3866
# enabled = false
3967

68+
# Background scheduler for persisted recurring tasks. The loop runs in
69+
# long-lived `chat` and `channel` sessions when enabled, and will post task
70+
# results back to the active bound thread when a live channel adapter exists.
71+
# [scheduler]
72+
# enabled = false
73+
# poll_interval_ms = 30000
74+
4075
# Built-in tools (local/file_read, local/file_write, local/file_list,
4176
# local/shell_exec) are always available. Additional MCP servers can be
4277
# configured below.

0 commit comments

Comments
 (0)