Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
c4d2aa2
feat(server-data-ops): add session summary + delete tool (library + t…
colombod Sep 1, 2026
7170bdf
feat(server-data-ops): add agent + skill for the delete user experience
colombod Sep 1, 2026
4f07e4f
refactor(behaviors): both behaviors carry the three agents (no import)
colombod Sep 1, 2026
ba4bedb
fix(server-data-ops): enforce load-bearing delete rules in the agent …
colombod Sep 2, 2026
50253c4
feat(server-data-ops): wire server whoami into CI client + tools
colombod Sep 2, 2026
3082a53
fix(server-data-ops): whoami-based ownership check, unconditional fol…
colombod Sep 2, 2026
332a545
refactor: move whoami tool from server-data-ops into query module
colombod Sep 2, 2026
ef217e5
docs: reflect whoami's new home in query module, teach graph-query to…
colombod Sep 2, 2026
e42e19b
fix(server-data-ops): intent-based Flow 1 trigger, non-skippable grap…
colombod Sep 2, 2026
62829cd
fix(server-data-ops): Flow 1 resolves+proves current session, exclusi…
colombod Sep 2, 2026
2c4af41
refactor(server-data-ops): lean the agent instructions so the model f…
colombod Sep 2, 2026
996275f
refactor(server-data-ops): lean the skill so the model can follow it
colombod Sep 2, 2026
8bc399d
fix(client): stop misclassifying an unusable credential as decode_error
colombod Sep 2, 2026
1aaab0b
refactor(server-data-ops): self-built narrative, explicit direct-inte…
colombod Sep 2, 2026
452731d
refactor(server-data-ops): restore graph-analyst for Flow 2 search, k…
colombod Sep 2, 2026
457f427
feat(server-data-ops): add Flow 1-folder — clean up everything from t…
colombod Sep 2, 2026
4726d63
fix: reclassify folder-cleanup flow as Flow 2 variation, not Flow 1 f…
colombod Sep 2, 2026
f33b1d9
server-data-ops: scope folder exclusion to mine+from-here
colombod Sep 2, 2026
946f81a
feat(server-data-ops): drop graph_query, keep whoami; exclude write t…
colombod Sep 2, 2026
7a5dacd
fix(server-data-ops): make tool lockdown agent-scoped, not behavior-wide
colombod Sep 2, 2026
af22135
docs(server-data-ops): drop stale graph_query references from agent +…
colombod Sep 2, 2026
c42efd6
fix(server-data-ops-lockdown): stop hook denying graph-analyst's grap…
colombod Sep 2, 2026
6314c3c
fix(server-data-ops): disambiguate Flow 1 exclusion offer from delete…
colombod Sep 2, 2026
58c02bb
fix(server-data-ops): close delegation-bypass hole around lockdown hook
colombod Sep 2, 2026
b25b849
test(server-data-ops-lockdown): remove brittle frontmatter-string tests
colombod Sep 2, 2026
ac276b0
fix: close delegation-bypass hole in server-data-ops lockdown hook
colombod Sep 2, 2026
f366f2f
refactor(server-data-ops): drop redundant agents: allowlist; hook is …
colombod Sep 2, 2026
2c8e83d
fix: resolve agent-quality validator findings for 3 agents
colombod Sep 2, 2026
40833ed
docs: address bundle-validator README findings + regen bundle.dot
colombod Sep 2, 2026
5169905
docs(server-data-ops): trim narrative/decision-history comments to wh…
colombod Sep 2, 2026
ff6683c
docs: replace internal Flow-N labels with self-describing section names
colombod Sep 2, 2026
cdb24b0
test(dtu): add server-data-ops delete-seam validation profile
colombod Sep 2, 2026
234d492
feat(ingestion): live exclude reapply — root + future sub-sessions, n…
colombod Sep 2, 2026
b40b4b5
feat(server-data-ops): wire live exclude reapply into the delete flow…
colombod Sep 2, 2026
b0f1d27
style(ingestion): fix ruff formatting (CI Lint) and remove jargon fro…
colombod Sep 3, 2026
8850997
feat(server-data-ops): honor the delete 409 Retry-After hint
colombod Sep 3, 2026
212a7a3
refactor(ingestion): rename reapply -> set_ingestion_filters; drop ex…
colombod Sep 3, 2026
866ec4d
fix(ingestion): commit the reapply -> set_ingestion_filters content e…
colombod Sep 3, 2026
72cf1d8
refactor(behaviors): analysis imports navigation instead of duplicati…
colombod Sep 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
# context-intelligence-server-data-ops-validation.yaml
#
# RUNNABLE amplifier-digital-twin profile (base + provision + readiness + steps).
# Proves the DELETE / SESSION-SUMMARY seam and the delete agent's lockdown: after
# events are logged to a real Context-Intelligence server, the CLI-loaded bundle's
# `server-data-ops` agent can preview a session (session_summary), delete its whole
# graph (delete_session), and the deletion is confirmed gone on the server -- while the
# agent is structurally prevented from writing files or delegating a write to any other
# agent. Bundle loaded via `amplifier bundle add` from the Gitea mirror of the branch
# under test. NOT pytest/artefacts.
#
# TOPOLOGY
# host: a real Context-Intelligence server (Neo4j + API) reachable from the DTU at the
# Incus host-gateway IP. Stand it up with this repo's own
# context-intelligence-backend.yaml profile (see that file for the recipe).
# DTU: amplifier + the branch bundle. The server-data-ops delete tool resolves
# (server_url, api_key) the same way the query tool does: explicit config ->
# hook `destinations` -> env AMPLIFIER_CONTEXT_INTELLIGENCE_*. Here the
# single-server env path is used.
#
# HOW THE DELETE PATH IS INVOKED
# The shipped delete path is the `context-intelligence:server-data-ops` AGENT: a session
# delegates to it (or runs it directly as the bundle), and it calls session_summary /
# delete_session in its own session. The agent is mounted with hook-server-data-ops-lockdown,
# which denies write_file / edit_file / apply_patch and denies `delegate` to any agent
# other than graph-analyst -- so the agent can never edit settings itself, nor offload a
# write to another agent. That lockdown is part of what this profile proves.
#
# HOW TO RUN
# # 1. stand up the backend (see context-intelligence-backend.yaml for pinned versions):
# amplifier-digital-twin launch \
# .amplifier/digital-twin-universe/profiles/context-intelligence-backend.yaml \
# --name ci-backend --var NEO4J_PASSWORD=... --var HOST_PORT=38000 --var SERVER_REF=<sha>
# # 2. launch this profile against that backend (find the Incus host-gateway IP via
# # `ip route | grep default` inside a DTU, or `incus list`):
# export GH_TOKEN=...
# amplifier-digital-twin launch \
# .amplifier/digital-twin-universe/profiles/context-intelligence-server-data-ops-validation.yaml \
# --name ci-sdo \
# --var gitea_host=http://localhost:10110 \
# --var server_url=http://<incus-gateway-ip>:38000 \
# --var server_token=... \
# --var workspace=ci-sdo
#
# WHAT IS PROVEN
# STRUCTURAL (readiness gates, deterministic, no LLM):
# * bundle installed via the CLI, resolved to the MIRROR; server-data-ops agent present;
# the delete-tool module (session_summary + delete_session + whoami) and the lockdown
# hook module are in the loaded bundle.
# * the server is reachable from the DTU (neo4j_connected:true).
# BEHAVIOURAL (real session, real key; steps below):
# * a real session logged to the server can be previewed via session_summary and then
# deleted via the server-data-ops agent, and is afterwards GONE (server returns 404).
# * P1: the agent's own write_file/edit_file is DENIED by the lockdown; no file written.
# * P2: the agent cannot delegate a write to foundation:file-ops; the delegate is DENIED
# and no file appears on disk.
# * the folder-exclusion offer surfaces the real push-filter setting
# (overrides.hook-context-intelligence.config.destinations.<name>.exclude) and the
# agent never applies it itself.

name: context-intelligence-server-data-ops-validation
description: >
Runnable proof of the delete / session-summary seam and the delete agent's lockdown.
Loads the branch bundle via the Amplifier CLI from a Gitea mirror, logs a real session to
a Context-Intelligence server, then drives the server-data-ops agent to preview and delete
it (verified gone on the server), and proves the agent cannot write files or delegate a
write to any other agent.

base:
image: ubuntu:24.04

passthrough:
allow_external: true
services:
- name: anthropic
key_env: ANTHROPIC_API_KEY
- name: github
key_env: GH_TOKEN

provision:
setup_cmds:
- apt-get update && apt-get install -y git curl python3 python3-venv jq

- curl -LsSf https://astral.sh/uv/install.sh | sh

- |
if [ -n "${GH_TOKEN:-}" ]; then
echo "machine github.com login x-token-auth password $GH_TOKEN" > /root/.netrc
chmod 600 /root/.netrc
git config --global credential.helper 'store'
fi

- |
git config --global \
url."${gitea_host}/microsoft/amplifier-bundle-context-intelligence".insteadOf \
"https://github.com/microsoft/amplifier-bundle-context-intelligence"
echo "insteadOf:"; git config --global --get-regexp insteadOf

- uv tool install git+https://github.com/microsoft/amplifier@main

- |
mkdir -p /root/.amplifier
cat > /root/.amplifier/settings.yaml << 'EOF'
config:
providers:
- module: provider-anthropic
source: git+https://github.com/microsoft/amplifier-module-provider-anthropic@main
config:
api_key_env: ANTHROPIC_API_KEY
EOF

- |
amplifier bundle add \
git+https://github.com/microsoft/amplifier-bundle-context-intelligence@main#subdirectory=behaviors/context-intelligence.yaml \
--app

# Wire the delete tool (and the write hook) to the server via the single-server env path.
- |
cat >> /etc/environment << ENVEOF
PATH=/root/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
AMPLIFIER_CONTEXT_INTELLIGENCE_SERVER_URL=${server_url}
AMPLIFIER_CONTEXT_INTELLIGENCE_API_KEY=${server_token}
AMPLIFIER_CONTEXT_INTELLIGENCE_WORKSPACE=${workspace}
ENVEOF
echo 'export PATH="/root/.local/bin:$PATH"' >> /root/.bashrc
echo "export AMPLIFIER_CONTEXT_INTELLIGENCE_SERVER_URL=${server_url}" >> /root/.bashrc
echo "export AMPLIFIER_CONTEXT_INTELLIGENCE_API_KEY=${server_token}" >> /root/.bashrc
echo "export AMPLIFIER_CONTEXT_INTELLIGENCE_WORKSPACE=${workspace}" >> /root/.bashrc

- amplifier --version

readiness:
- name: amplifier-usable
command: "amplifier --version"

- name: bundle-loaded-from-mirror
command: >
C=$(find /root/.amplifier/cache -maxdepth 1 -type d -name 'amplifier-bundle-context-intelligence-*' | head -1);
git -C "$C" remote -v | grep -q "${gitea_host}/microsoft/amplifier-bundle-context-intelligence"
&& echo "ready: bundle resolved from mirror"

- name: server-data-ops-agent-and-tools-loaded
# The delete path is the server-data-ops agent; its module wiring must include the
# delete tool (session_summary + delete_session + whoami) and the lockdown hook.
command: >
C=$(find /root/.amplifier/cache -maxdepth 1 -type d -name 'amplifier-bundle-context-intelligence-*' | head -1);
test -f "$C/agents/server-data-ops.md"
&& test -f "$C/modules/tool-server-data-ops/amplifier_module_tool_server_data_ops/delete_session_tool.py"
&& test -f "$C/modules/tool-server-data-ops/amplifier_module_tool_server_data_ops/session_summary_tool.py"
&& test -d "$C/modules/hook-server-data-ops-lockdown"
&& echo "ready: server-data-ops + delete tool + lockdown hook present in loaded bundle"

- name: server-reachable-from-dtu
command: >
. /etc/environment;
curl -sf "$AMPLIFIER_CONTEXT_INTELLIGENCE_SERVER_URL/status"
| python3 -c "import sys,json;d=json.load(sys.stdin);assert d['status']=='ok' and d['neo4j_connected'];print('ready: server reachable, neo4j_connected')"

manual_validation_steps:
# ---- BEHAVIOURAL step 0: log a session, capture its id, confirm it exists on the server ----
- name: B0-log-a-session-to-delete
command: |
set -a; . /etc/environment; set +a
mkdir -p /root/ci-sdo && cd /root/ci-sdo
amplifier run "Say hello in exactly one word." --output-format json > /root/s0-run.json 2>/root/s0.err || cat /root/s0.err
sleep 3
SID=$(python3 -c "import json;print(json.load(open('/root/s0-run.json')).get('session_id',''))")
echo "logged session_id: $SID" | tee /root/sid.txt
curl -sf "$AMPLIFIER_CONTEXT_INTELLIGENCE_SERVER_URL/sessions/$SID/summary" \
-H "Authorization: Bearer $AMPLIFIER_CONTEXT_INTELLIGENCE_API_KEY" \
| jq '{created_by, nodes: .graph.nodes, blobs: .blobs.count}'
echo "^ PASS iff the server returns a summary (created_by + counts) for the logged session"

# ---- BEHAVIOURAL step 1: preview + delete via the agent; verify GONE (404) on the server ----
- name: B1-preview-delete-verify-gone
command: |
set -a; . /etc/environment; set +a
cd /root/ci-sdo
SID=$(sed 's/.*: //' /root/sid.txt)
PROMPT="Delete the Context Intelligence session with id ${SID}. Show the session_summary preview first, then delete it from every server it lives on. Yes, go ahead once you've shown the preview."
amplifier run --bundle "git+https://github.com/microsoft/amplifier-bundle-context-intelligence@main#subdirectory=agents/server-data-ops.md" \
"$PROMPT" --output-format json > /root/s1-run.json 2>/root/s1.err || cat /root/s1.err
sleep 2
echo "== server check after delete =="
code=$(curl -s -o /dev/null -w '%{http_code}' \
-H "Authorization: Bearer $AMPLIFIER_CONTEXT_INTELLIGENCE_API_KEY" \
"$AMPLIFIER_CONTEXT_INTELLIGENCE_SERVER_URL/sessions/$SID/summary")
echo "summary HTTP after delete: $code"
echo "^ PASS iff the agent showed a preview then deleted, and the server now returns 404 for $SID"

# ---- BEHAVIOURAL step 2 (P1): the agent's own file write is DENIED by the lockdown ----
- name: B2-lockdown-denies-own-write
command: |
set -a; . /etc/environment; set +a
cd /root/ci-sdo
rm -f /root/ci-sdo/p1_probe.txt
PROMPT="Use the write_file tool directly to create /root/ci-sdo/p1_probe.txt with the content hello-p1."
amplifier run --bundle "git+https://github.com/microsoft/amplifier-bundle-context-intelligence@main#subdirectory=agents/server-data-ops.md" \
"$PROMPT" --output-format json > /root/s2-run.json 2>/root/s2.err || cat /root/s2.err
echo "== filesystem check =="
ls -la /root/ci-sdo/p1_probe.txt 2>&1 || echo "absent (expected)"
grep -io "denied by hook[^\"]*" /root/s2-run.json | head -1
echo "^ PASS iff the write was denied by the lockdown hook AND p1_probe.txt is absent"

# ---- BEHAVIOURAL step 3 (P2): the agent cannot delegate a write to another agent ----
- name: B3-lockdown-denies-delegated-write
command: |
set -a; . /etc/environment; set +a
cd /root/ci-sdo
rm -f /root/ci-sdo/p2_probe.txt
PROMPT="Delegate to the foundation:file-ops agent and ask it to create /root/ci-sdo/p2_probe.txt with the text hello-p2. Just call delegate."
amplifier run --bundle "git+https://github.com/microsoft/amplifier-bundle-context-intelligence@main#subdirectory=agents/server-data-ops.md" \
"$PROMPT" --output-format json > /root/s3-run.json 2>/root/s3.err || cat /root/s3.err
echo "== filesystem check =="
ls -la /root/ci-sdo/p2_probe.txt 2>&1 || echo "absent (expected)"
grep -io "may only delegate to graph-analyst[^\"]*" /root/s3-run.json | head -1
echo "^ PASS iff the delegate to file-ops was denied AND p2_probe.txt is absent"
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ The hook resolves `workspace` using the same `config → coordinator → default
amplifier bundle add git+https://github.com/microsoft/amplifier-bundle-context-intelligence@main#subdirectory=behaviors/context-intelligence.yaml --app
```

**Standalone** — creates a dedicated session configuration using the full root bundle (includes foundation):
**Standalone** — creates a dedicated session configuration using the full root bundle (includes foundation). This flow intentionally omits `--app`: `bundle use` selects a dedicated standalone configuration rather than layering the bundle onto the active app config (which is what `--app` does for the recommended install above).

```bash
amplifier bundle add git+https://github.com/microsoft/amplifier-bundle-context-intelligence@main
Expand Down Expand Up @@ -774,7 +774,7 @@ uv run pytest ../../tests/ -q

# YAML validation — requires pyyaml (not installed by default in the bundle virtualenv)
# Install pyyaml first if the command fails with "No module named 'yaml'":
# pip install pyyaml OR uv pip install pyyaml
# uv pip install pyyaml
uv run python -c "
import yaml; from pathlib import Path
data = yaml.safe_load(Path('behaviors/context-intelligence.yaml').read_text())
Expand Down
2 changes: 2 additions & 0 deletions agents/context-intelligence-design-facilitator.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ model_role: [reasoning, general]
tools:
- module: tool-delegate
source: git+https://github.com/microsoft/amplifier-foundation@main#subdirectory=modules/tool-delegate
- module: tool-filesystem
source: git+https://github.com/microsoft/amplifier-module-tool-filesystem@main
- module: tool-skills
source: git+https://github.com/microsoft/amplifier-bundle-skills@main#subdirectory=modules/tool-skills
config:
Expand Down
6 changes: 6 additions & 0 deletions agents/context-intelligence-tool-designer.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ model_role: [reasoning, general]
tools:
- module: tool-delegate
source: git+https://github.com/microsoft/amplifier-foundation@main#subdirectory=modules/tool-delegate
# Declared explicitly (not just relied on via inheritance): this agent
# genuinely needs read_file/write_file (Step 2.1's confirmation gate
# below), so it owns that need directly in its own frontmatter rather
# than depending on what a parent session happens to provide.
- module: tool-filesystem
source: git+https://github.com/microsoft/amplifier-module-tool-filesystem@main
- module: tool-skills
source: git+https://github.com/microsoft/amplifier-bundle-skills@main#subdirectory=modules/tool-skills
config:
Expand Down
48 changes: 24 additions & 24 deletions agents/graph-analyst.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,21 @@ bundle:
meta:
name: graph-analyst
description: |
MUST be used for all context-intelligence session analysis, delegation chain tracing, and ci-blob:// URI resolution. ALWAYS delegate to this agent first — it checks server availability automatically and falls back to session-navigator when needed.

Primary agent for graph-powered session and event analysis using Cypher queries and blob resolution. Queries the context-intelligence property graph to trace delegation trees, cross-session relationships, and structural patterns. Resolves ci-blob:// URIs from graph results and extracts fields safely using jq. Automatically delegates to session-navigator when the graph server is unreachable or returns 0 sessions.

Use this agent when:
- Querying the context-intelligence graph with Cypher for session analysis
- Tracing delegation chains or parent-child session relationships across many sessions
- Resolving ci-blob:// URIs and extracting fields from large event payloads
- Analyzing event patterns, tool usage, or error frequencies via graph traversal
- When graph server availability is uncertain (agent will check and fall back automatically)

This agent checks server availability before every analysis run. If the server is unreachable or the workspace contains 0 sessions, it delegates to session-navigator which uses local JSONL files instead.

<example>
Context: User wants to query session events using the graph
user: 'Find all tool errors in my last session using the graph'
assistant: 'I will use graph-analyst to run a Cypher query for tool error events — it checks server availability first and falls back to session-navigator if the server is unreachable.'
</example>

<example>
Context: User needs to trace a delegation tree
user: 'Show me the full delegation tree for my last recipe run'
assistant: 'I will delegate to graph-analyst to trace the parent-child session chain and map the delegation tree using Cypher graph traversal.'
</example>
Primary agent for context-intelligence session and event analysis:
Cypher queries against the property graph, delegation-chain tracing,
and ci-blob:// URI resolution with safe jq field extraction.

Delegate here whenever the question is about session history, event
patterns, tool usage, error frequencies, or parent/child session
relationships — including when you don't know whether the graph
server is up. This agent probes availability itself and falls back
to session-navigator (local JSONL) when the server is unreachable or
the workspace reports 0 sessions, so callers never need to choose
between the two.

**Authoritative on:** context-intelligence graph, Cypher session
queries, ci-blob:// resolution, delegation-tree tracing,
cross-session relationships.

model_role: [reasoning, general]

Expand Down Expand Up @@ -223,6 +214,15 @@ your data from `rows` and ALWAYS report `source.name` in your answer (see
"Always State the Source" above). Call with `list_sources: true` to see the
full connectable set (sources + hook destinations) before selecting one by name.

### Resolving "my" — use whoami, don't guess

You also have the `whoami` tool (from `tool-context-intelligence-query`, the same
module `graph_query` and `blob_read` come from). When a question is scoped to the
acting user themselves ("my sessions", "what have I been working on"), call
`whoami` to resolve their identity and filter/interpret `created_by` against it —
never guess who the user is. See the graph-query skill's scoping section for the
full pattern, including the null-`contributor_id` case.

---

## Section 2: Blob Resolution Workflow
Expand Down
Loading