Skip to content

Commit bb95bcb

Browse files
samples: make behavioral monitor a real AgentChat demo
1 parent 775406f commit bb95bcb

2 files changed

Lines changed: 193 additions & 147 deletions

File tree

python/samples/agentchat_behavioral_monitor/README.md

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
# agentchat_behavioral_monitor
22

3-
Detect vocabulary and topic drift in long AutoGen conversations.
3+
Detect vocabulary drift across repeated AgentChat runs.
44

5-
When an AutoGen conversation runs long enough to trigger history summarization
6-
or truncation, earlier task context can vanish without any visible signal. The
7-
agent keeps responding, but its answers may silently ignore facts it established
8-
in earlier turns — different tool choices, forgotten constraints, missing domain
9-
vocabulary.
5+
When a long-running agent shifts away from earlier task vocabulary, the failure
6+
often shows up first as a change in outputs rather than an explicit error. This
7+
sample shows how to watch for that drift on the public AgentChat surface.
108

11-
This sample shows how to detect that drift using **Ghost Consistency Score
12-
(CCS)**: the fraction of vocabulary from the earliest turns still present in
13-
the most recent turns. A score below 0.40 indicates likely behavioral drift.
9+
The demo is deterministic: it uses `ReplayChatCompletionClient` together with a
10+
real `AssistantAgent`, then monitors the resulting `TaskResult.messages`
11+
history. In production, replace the replay model with a real model client and
12+
keep the same monitor.
13+
14+
This sample detects drift using **Ghost Consistency Score (CCS)**: the fraction
15+
of vocabulary from the earliest runs still present in the most recent runs. A
16+
score below 0.40 indicates likely behavioral drift.
1417

1518
## How it works
1619

@@ -20,7 +23,8 @@ Current window = last 25% of conversation turns
2023
CCS = |vocab(baseline) ∩ vocab(current)| / |vocab(baseline)|
2124
```
2225

23-
A "ghost term" is a task-relevant word (jwt, bcrypt, foreign_key, redis, etc.)
26+
A "ghost term" is a task-relevant word (`jwt`, `bcrypt`, `foreign_key`,
27+
`redis`, etc.)
2428
that appeared in the baseline window but has disappeared from the current
2529
window. Ghost terms are the most direct signal of forgotten context.
2630

@@ -33,38 +37,49 @@ python main.py
3337
Expected output:
3438

3539
```
36-
=== AutoGen Behavioral Monitor demo ===
37-
Turn : 8
38-
CCS : 0.333 (1.0 = no drift, <0.4 = significant drift)
39-
Ghost terms : ['bcrypt', 'foreign_key', 'redis', 'jwt']
40-
Unretrieved : True
41-
Drift detected: True
40+
=== AutoGen AgentChat behavioral monitor demo ===
41+
42+
Turn 1
43+
CCS: 1.0
44+
Ghost terms: []
45+
Drift detected: False
4246
43-
Interpretation: the agent has drifted from its early task vocabulary.
44-
If ghost terms include task-critical facts, consider re-injecting context
45-
or prompting the agent to recall those items from its memory store.
47+
Turn 3
48+
CCS: 0.25
49+
Ghost terms: ['bcrypt', 'foreign_key', 'jwt', 'redis']
50+
Drift detected: True
4651
```
4752

4853
## Integrating into your agent loop
4954

5055
```python
56+
from autogen_agentchat.agents import AssistantAgent
57+
from autogen_ext.models.replay import ReplayChatCompletionClient
5158
from main import BehavioralMonitor
5259

5360
monitor = BehavioralMonitor(
5461
ccs_threshold=0.40,
55-
min_messages=6,
62+
min_messages=3,
5663
)
5764

5865
history = []
66+
agent = AssistantAgent(
67+
"assistant",
68+
model_client=ReplayChatCompletionClient([
69+
"Use jwt and bcrypt for auth.",
70+
"Keep jwt auth intact for the profile endpoint.",
71+
"Add endpoint rate limiting.",
72+
]),
73+
)
5974

6075
# Check after each public AgentChat run
61-
task_result = await assistant_agent.run(task="Use jwt and bcrypt for auth")
76+
task_result = await agent.run(task="Use jwt and bcrypt for auth", output_task_messages=False)
6277
result = monitor.observe_result(history, task_result)
6378
if result["drift_detected"]:
6479
print("Drift at turn", result["turn"], "ghost:", result["ghost_terms"])
6580

6681
# Later runs keep extending the same external history
67-
task_result = await assistant_agent.run(task="Now add a profile endpoint")
82+
task_result = await agent.run(task="Now add a profile endpoint", output_task_messages=False)
6883
result = monitor.observe_result(history, task_result)
6984
```
7085

@@ -73,15 +88,15 @@ result = monitor.observe_result(history, task_result)
7388
| Parameter | Default | Description |
7489
|---|---|---|
7590
| `ccs_threshold` | 0.40 | Flag drift when CCS drops below this value |
76-
| `min_messages` | 6 | Minimum conversation length before checks run |
91+
| `min_messages` | 3 | Minimum number of tracked AgentChat results before checks run |
7792
| `ghost_lexicon` | built-in list | Domain terms to watch for disappearance |
7893

7994
## Connection to AutoGen issue #7265
8095

8196
This sample addresses the production reliability pattern discussed in
8297
https://github.com/microsoft/autogen/issues/7265 — specifically the
83-
ghost-lexicon + behavioral footprint pattern for detecting when long-running
84-
agents silently lose task context to compression.
98+
ghost-lexicon pattern for detecting when long-running agent outputs silently
99+
drift away from earlier task vocabulary.
85100

86101
## Related
87102

0 commit comments

Comments
 (0)