fabro/lib/crates/fabro-agent/src
fabro-sh-0530[bot] a2e2cbc7ed
Add agent context observability events (memory, skills, MCP tools) (#356)
## Summary

Adds three new durable run events — `agent.memory.loaded`,
`agent.skills.discovered`, and `agent.skill.activated` — and enriches
`agent.mcp.ready` with names-only tool summaries. Consumers can now
reconstruct what memory, skills, and MCP tools were active for any agent
run by reading the event stream, without needing to inspect session
state.

### Plan Summary

- **`fabro-types`**: New prop structs (`AgentMemoryLoadedProps`,
`AgentSkillsDiscoveredProps`, `AgentSkillActivatedProps`,
`AgentMcpToolSummary`) and three new `EventBody` variants with canonical
dot-name serialization. `AgentMcpReadyProps.tools` uses
`#[serde(default, skip_serializing_if = "Vec::is_empty")]` for backwards
compatibility.
- **`fabro-agent/memory.rs`**: `discover_memory` now returns
`Vec<MemoryDocument>` carrying path, byte counts, and truncation flag
alongside content. The content itself is never put in any event payload.
- **`fabro-agent/types.rs`**: Adds `MemoryLoaded`, `SkillsDiscovered`,
`SkillActivated`, and enriched `McpServerReady` internal variants.
Removes `SkillExpanded` (replaced by `SkillActivated { source: Slash
}`). New variants are **not** classified as streaming noise, so they
persist.
- **`fabro-agent/session.rs`**: Emits `MemoryLoaded` before skills init,
`SkillsDiscovered` after skill discovery, and enriches `McpServerReady`
with summaries from `McpConnectionManager::tool_summaries_for_server`.
Slash expansion now emits `SkillActivated { source: Slash }` instead of
`SkillExpanded`.
- **`fabro-agent/skills.rs`**: `make_use_skill_tool` emits
`SkillActivated { source: Tool }` on successful lookup only.
- **`fabro-mcp/connection_manager.rs`**: New `tool_summaries_for_server`
returns sorted `(qualified_name, original_name)` pairs without leaking
descriptions or schemas.
- **`fabro-workflow/event/convert.rs` + `names.rs`**: Converts all new
agent events to their typed `fabro-types` props, including `visit`
injection. Removes dead `SkillExpanded` arm.
- **`docs/internal/events.md`**: Documents all new event shapes with
full property tables; notes that `agent.skill.expanded` is replaced.

### Key design decisions

- Both `MemoryLoaded` and `SkillsDiscovered` are emitted even when the
result is empty. This lets consumers distinguish "no memory/skills
found" from "event not yet reported."
- Memory file **contents are never included** in any event payload —
only `path`, `byte_count`, `loaded_bytes`, and `truncated`.
- `agent.mcp.ready` `tools` field is omitted from JSON when empty
(`skip_serializing_if`), preserving wire compatibility with existing
stored events.
- `SkillActivated` is persisted (not filtered as streaming noise),
unlike the former internal-only `SkillExpanded`.


### Fabro Details

<details>
<summary>Ran 9 stages in 57m 15s for $27.15</summary>

| Stage | Duration | Cost | Retries |
|---|---|---|---|
| start | 0s | – | 0 |
| toolchain | 1s | – | 0 |
| preflight_compile | 2m 17s | – | 0 |
| preflight_lint | 2m 30s | – | 0 |
| implement | 21m 18s | $16.27 | 0 |
| simplify_opus | 15m 21s | $6.52 | 0 |
| simplify_gpt | 10m 33s | $4.35 | 0 |
| verify | 4m 24s | – | 0 |
| fmt | 3s | – | 0 |
| **Total** | **57m 15s** | **$27.15** | **0** |

</details>

<details>
<summary>Ran <code>ImplementPlan.fabro</code> (12 nodes and 15
edges)</summary>

```dot
digraph ImplementPlan {
    graph [
        goal="Implement and simplify",
        model_stylesheet="
            * { model: claude-opus-4-7; }
        "
    ]
    rankdir=LR

    start [shape=Mdiamond, label="Start"]
    exit  [shape=Msquare, label="Exit"]

    toolchain         [label="Toolchain", shape=parallelogram, script="command -v cargo >/dev/null || { curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && sudo ln -sf $HOME/.cargo/bin/* /usr/local/bin/; }; cargo --version 2>&1", max_retries=0]
    preflight_compile [label="Preflight Compile", shape=parallelogram, script="cargo check -q --workspace 2>&1", max_retries=0]
    preflight_lint    [label="Preflight Lint", shape=parallelogram, script="cargo +nightly-2026-04-14 clippy -q --workspace --all-targets -- -D warnings 2>&1", max_retries=0]
    fix_lints         [label="Fix Lints", prompt="The preflight lint step failed. Read the build output from context and fix all clippy lint warnings.", max_visits=3]
    implement         [label="Implement", prompt="Read the plan file referenced in the goal and implement every step. Make all the code changes described in the plan. Use red/green TDD."]
    simplify_opus     [label="Simplify (Opus)", prompt="@prompts/simplify.md"]
    simplify_gpt      [label="Simplify (GPT-55)", prompt="@prompts/simplify.md", model="gpt-55"]
    verify            [label="Verify", shape=parallelogram, script="cargo +nightly-2026-04-14 clippy -q --workspace --all-targets -- -D warnings 2>&1 && cargo nextest run --cargo-quiet --workspace --status-level fail 2>&1 && cargo dev docs refresh 2>&1 && cargo dev docs check 2>&1", goal_gate=true, retry_target="fixup"]
    fixup             [label="Fixup", prompt="The verify step failed. Read the build output from context and fix all clippy lint warnings, test failures, and generated docs errors.", max_visits=3]
    fmt               [label="Format", shape=parallelogram, script="cargo +nightly-2026-04-14 fmt --all 2>&1", max_retries=0]

    start -> toolchain
    toolchain -> preflight_compile [condition="outcome=succeeded"]
    toolchain -> exit
    preflight_compile -> preflight_lint [condition="outcome=succeeded"]
    preflight_compile -> exit
    preflight_lint -> implement [condition="outcome=succeeded"]
    preflight_lint -> fix_lints
    fix_lints -> preflight_lint
    implement -> simplify_opus -> simplify_gpt -> verify
    verify -> fmt   [condition="outcome=succeeded"]
    verify -> fixup
    fixup -> verify
    fmt -> exit
}

```

</details>

⚒️ Generated with [Fabro](https://fabro.sh)

---------

Co-authored-by: Fabro <noreply@fabro.sh>
2026-05-22 19:06:00 -04:00
..
profiles Add event-sourced todo tools for OpenAI and Anthropic profiles (#353) 2026-05-22 13:44:42 -04:00
agent_profile.rs refactor(llm): split provider identity from adapters (#280) 2026-05-16 13:13:41 -04:00
apply_patch.lark feat(agent): make OpenAI apply_patch Codex-compatible (#350) 2026-05-22 10:30:18 -04:00
apply_patch.rs Add event-sourced todo tools for OpenAI and Anthropic profiles (#353) 2026-05-22 13:44:42 -04:00
cli.rs feat(api): bind sessions to runs (#336) 2026-05-21 10:53:41 -04:00
compaction.rs feat(session): add server-backed agent sessions (#278) 2026-05-16 17:25:05 -04:00
config.rs feat(agent): gate tools by effective access policy 2026-05-22 13:16:56 -04:00
docker_sandbox.rs Rename SessionConfig to SessionOptions and McpServerConfig to McpServerSettings 2026-04-02 06:47:42 -07:00
error.rs fmt: apply nightly rustfmt after merge 2026-04-11 13:43:30 -04:00
event.rs Add event-sourced todo tools for OpenAI and Anthropic profiles (#353) 2026-05-22 13:44:42 -04:00
file_tracker.rs feat(agent): make OpenAI apply_patch Codex-compatible (#350) 2026-05-22 10:30:18 -04:00
history.rs feat(session): add server-backed agent sessions (#278) 2026-05-16 17:25:05 -04:00
lib.rs Add agent context observability events (memory, skills, MCP tools) (#356) 2026-05-22 19:06:00 -04:00
local_sandbox.rs Create fabro-sandbox crate, consolidating Sandbox trait and all implementations 2026-03-19 20:06:19 -04:00
loop_detection.rs feat(session): add server-backed agent sessions (#278) 2026-05-16 17:25:05 -04:00
mcp_integration.rs Add event-sourced todo tools for OpenAI and Anthropic profiles (#353) 2026-05-22 13:44:42 -04:00
memory.rs Add agent context observability events (memory, skills, MCP tools) (#356) 2026-05-22 19:06:00 -04:00
read_before_write_sandbox.rs Create fabro-sandbox crate, consolidating Sandbox trait and all implementations 2026-03-19 20:06:19 -04:00
sandbox.rs Add ACP backend support (#237) 2026-05-11 23:39:43 -04:00
session.rs Add agent context observability events (memory, skills, MCP tools) (#356) 2026-05-22 19:06:00 -04:00
skills.rs Add agent context observability events (memory, skills, MCP tools) (#356) 2026-05-22 19:06:00 -04:00
subagent.rs Add event-sourced todo tools for OpenAI and Anthropic profiles (#353) 2026-05-22 13:44:42 -04:00
test_support.rs refactor(llm): split provider identity from adapters (#280) 2026-05-16 13:13:41 -04:00
todo_runtime.rs Add event-sourced todo tools for OpenAI and Anthropic profiles (#353) 2026-05-22 13:44:42 -04:00
todo_tools.rs Add event-sourced todo tools for OpenAI and Anthropic profiles (#353) 2026-05-22 13:44:42 -04:00
tool_execution.rs test(agent): pass root session id in tool execution tests 2026-05-22 14:33:37 -04:00
tool_permissions.rs feat(api): bind sessions to runs (#336) 2026-05-21 10:53:41 -04:00
tool_registry.rs Merge remote-tracking branch 'origin/main' into ask-fabro-welcome-prompts 2026-05-22 13:46:03 -04:00
tools.rs Add event-sourced todo tools for OpenAI and Anthropic profiles (#353) 2026-05-22 13:44:42 -04:00
truncation.rs refactor: unify metadata snapshot failure helpers and drop floor_char_boundary copies 2026-05-01 09:17:47 -04:00
types.rs Add agent context observability events (memory, skills, MCP tools) (#356) 2026-05-22 19:06:00 -04:00