Agentic provenance: framework plugins, AI-coding-harness capture, and provenance analysis - #351
Open
GueroudjiAmal wants to merge 31 commits into
Open
Agentic provenance: framework plugins, AI-coding-harness capture, and provenance analysis#351GueroudjiAmal wants to merge 31 commits into
GueroudjiAmal wants to merge 31 commits into
Conversation
Main <- Dev
# Conflicts: # README.md # resources/sample_settings.yaml # src/flowcept/agents/__init__.py # src/flowcept/commons/daos/mq_dao/mq_dao_base.py # src/flowcept/flowcept_api/flowcept_controller.py # src/flowcept/version.py
Upstream now resolves settings to plain containers at load time, so the OmegaConf.to_container call on the plugins block failed with a plain dict. Also run ruff format over src so 'make checks' formatting passes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Capture what an AI coding harness actually did - prompts, turns, tool
calls, subagents - as PROV-AGENT provenance, following the same
per-framework plugin layout as the academy/langgraph/crewai/autogen
plugins:
src/flowcept/agents/harness/ shared capture core (stdlib-only)
src/flowcept/agents/claude_code/ Claude Code hook adapter
src/flowcept/agents/cli_harness/ profile-driven adapter (codex,
gemini, cursor, opencode)
src/flowcept/agents/otel/ OTel GenAI span exporter/ingest
src/flowcept/agents/claude_agent_sdk/ trace_query wrapper
src/flowcept/agents/openai_agents/ tracing processor
src/flowcept/agents/langchain/ callback handler
plugins/flowcept/ the Claude Code plugin
tests/harness/ test suite (87 tests)
examples/agents/harness/ SessionTracer example
flowcept.agents.__init__ becomes lazy (PEP 562): the MCP tool modules
pull optional heavy deps, and this package is now on the import path of
capture hooks that run on the interactive critical path.
New console scripts: flowcept-harness, flowcept-harness-mcp,
flowcept-claude-code. New extras: harness_otel, harness_claude_sdk.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Preserve the full harness documentation (configuration table, privacy posture, record model, design constraints) as the harness package's own README, and link it from the main README. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… fix issues found
Ran every plugin against the real thing (academy 0.5, langgraph, crewai,
autogen-agentchat, claude-agent-sdk, openai-agents via Anthropic's
OpenAI-compatible endpoint, codex hook profile, online Redis MQ -> LMDB
-> query, harness flush -> live backend). Fixes that fell out:
- examples: pick the LLM provider from the environment (ANTHROPIC_API_KEY
-> anthropic_chat, else openai_chat), so they run with either key
- examples/academy: academy 0.5 removed academy.logging.init_logging;
use logging.basicConfig
- examples/autogen: the result parser dropped ints followed by
punctuation ('15.'), so the assertion read 5 instead of 15
- plugins: default Anthropic model claude-3-5-haiku-latest no longer
exists; use claude-haiku-4-5-20251001
- harness flush: stop the MQ with check_safe_stops=False; the control
messages it sent carried a None interceptor id that crashed the
document inserter
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds the missing pydocstyle docstrings (D102/D103/D105/D205/D400/D401) in the new agent plugin and harness modules, moves a misplaced import (E402), and fixes an undefined ProcessPoolExecutor name in the academy plugin's type annotation (F821) via a TYPE_CHECKING import. No logic changes; ruff check --select D,E,F,W and ruff format are clean on all touched files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Unit tests (68 new, tests/agents/plugins/) for the academy, autogen, crewai, and langgraph provenance plugins plus cross-framework linking (_source_agent_id), driving the real plugin code against an in-memory interceptor fake; each module importorskips its framework so CI without the frameworks skips cleanly. No network, MQ, or LLM keys. - Runnable examples for the six plugins that only had README snippets: langchain, openai_agents, otel, cli_harness, claude_code, and claude_agent_sdk; all verified end-to-end (five run fully offline). - New Sphinx pages docs/agent_plugins.rst and docs/harness_plugins.rst wired into the toctree; build is clean with no new warnings. - src/flowcept/agents/README.md now indexes all agent subpackages and links the harness README, docs pages, and examples; top-level README examples list extended. - Regenerated docs/openapi specs (stale: missing the root health route). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- tests/harness/test_generic.py: four gemini-CLI event-replay tests (session fields, nested toolCall mapping, prompt+response turn, tool error), matching the coverage codex/cursor/opencode already had, plus docstrings on the pre-existing tests. - tests/harness/test_cross_capture.py (new, 6 tests): source_agent_id round-trip through the harness provenance builder and buffer; shared campaign_id joining harness and LangGraph plugin records (config and env paths); simultaneous harness SessionTracer + LangGraph capture in one process with disjoint ids; and a real harness tool task_id linked into a LangGraph run via _source_agent_id. Note: harness-side emission of source_agent_id has no caller yet (recorder never passes it); tested at the builder/emitter level only. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… hooks New src/flowcept/agents/prov_analysis/ package: seven dependency-light analysis functions over PROV-AGENT records (summarize_execution, analyze_errors, analyze_agent_behavior, find_slowest_tasks, cross_framework_links, compare_executions, load_records), handling both harness-buffer and framework-plugin record shapes and reusing report.aggregations primitives. Surfaces: - Harness MCP server: analyze_session, analyze_errors, find_slowest, cross_links (stdio, JSONL-only, no DB required). - Flowcept agent MCP: df_*/db_* analysis tools plus compare_executions, also exposed to the web chat via the LangChain tool registry. - CLI: flowcept-harness analyze <session> [--errors|--slowest N|--links]. - Claude Code plugin v0.2.0: .mcp.json wiring the flowcept-provenance stdio server; new skills prov-analysis (how to analyze captured provenance) and write-flowcept-plugin (how to author a new provenance plugin); opt-in SessionEnd auto-report hook gated by FLOWCEPT_HARNESS_AUTOREPORT=1. 57 new offline tests (core, MCP registration, harness tools, CLI, plugin assets) — suite now 235 passing. Offline example added and executed; Sphinx docs (agent.rst, harness_plugins.rst) and READMEs updated with zero new build warnings. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ning - Harness records (turns, tool calls, LLM calls) can now link back to a framework-emitted task: source_agent_id flows from the hook payload key flowcept_source_agent_id (wins) or env FLOWCEPT_HARNESS_SOURCE_AGENT_ID, through HarnessEvent and the recorder; SessionTracer accepts source_agent_id= as sticky context. cross_framework_links picks the new edges up unchanged. - OTel plugin: session identity no longer derives from gen_ai.system, which split one conversation into multiple workflows when the attribute was inconsistent; identity now comes from the conversation id only, and the provider name is recorded first-wins as a one-time lifecycle notice. Reproduced failing-first in tests. - flowcept-harness analyze --compare A B: per-activity count, duration, and error-rate deltas between two session buffers. - CI: pin ruff==0.15.22 (unpinned latest fails even upstream main; make checks passes clean under the pin) and fail if the committed OpenAPI spec drifts from regeneration. - .gitignore: narrow core.* (meant for core dumps) to core.[0-9]* so it cannot swallow Python modules named core.py. 10 new tests; suite now 245 passing, all offline. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR extends Flowcept's provenance capture from scientific workflows to agentic systems: agent frameworks (Academy, LangGraph, CrewAI, AutoGen, LangChain, OpenAI Agents SDK, Claude Agent SDK), AI coding harnesses (Claude Code, Codex CLI, Gemini CLI, Cursor, OpenCode, or anything emitting OpenTelemetry GenAI spans), and a shared provenance-analysis layer that all of these — plus the existing MCP agent, the webservice chat, and the CLI — query through one set of functions.
The framing follows PROV-AGENT: an agentic session is a workflow — a prompt causes a turn, a turn causes tool calls, a tool call edits a file — which is the structure Flowcept already stores and queries. It also adds a Diaspora MQ adapter, which came along on the same branch (see Should this be split? below).
What's included
1. Agent-framework plugins (
src/flowcept/agents/{academy,langgraph,crewai,autogen,langchain,openai_agents,claude_agent_sdk}/)Each plugin captures its framework's execution as Flowcept tasks/workflows. They are declarative — no code changes in user workloads:
Flowcept.start()builds, starts, and stops enabled plugins alongside Flowcept, propagatingcampaign_idso all plugins in a run share a campaign. Running instances are exposed via the newFlowcept.pluginsproperty. Each plugin's interceptor reuses theInstrumentationInterceptorsingleton (same MQ connection and buffer) — the pattern the Dask client interceptor already uses. A plugin that fails to start is logged and skipped rather than taking Flowcept down.2. AI coding harness capture (
src/flowcept/agents/harness/+ per-harness plugin modules)Shared capture core (
recorder,tracer,emit,events,prov,state,sanitize,ids,vocab,config,cli,mcp_server) with these sources:settings.jsoncli_harness/profiles/*.json)SessionTracer, or the MCP server'srecord_eventtoolThe capture path is deliberately stdlib-only — it imports nothing outside
flowcept.agents.harnessand the standard library. A harness hook is a fresh process on the interactive critical path, so importing Flowcept's heavy dependencies would cost far more than the capture itself; those are loaded only to read what was captured. Adding a new CLI harness means adding a JSON profile, not writing code.New entry points:
flowcept-harness(sessions/show/report/analyze/install/hook/compare),flowcept-harness-mcp,flowcept-claude-code.3. Provenance analysis (
src/flowcept/agents/prov_analysis/)Framework-free pure functions over
records: list[dict], following the existingdata_query_tools/layering rule (cores are framework-free; MCP/LangChain wrappers are thin):summarize_execution,analyze_errors,analyze_agent_behavior,find_slowest_tasks,cross_framework_links,compare_executions. They handle both the harness-buffer record shape and the framework-plugin shape, degrading gracefully on absent fields.Four surfaces share this one implementation: the harness MCP server, the Flowcept agent MCP server (new
mcp/mcp_tools/analysis_mcp_tools.py, registered inmcp/mcp_server.py), the webservice chat (chat_orchestration/tool_registry.py), andflowcept-harness analyze.cross_framework_linksbuilds edges fromsource_agent_idpointers, so a task recorded by one plugin can be linked to the agent that caused it in another.4. Diaspora MQ adapter
MQDaoDiaspora(commons/daos/mq_dao/mq_dao_diaspora.py), wired into theMQDao.build()dispatch asmq.type: diaspora, plusresources/diaspora/setup scripts anddeployment/compose-diaspora.yml.5. Smaller core changes
configs.py: newPLUGINSsettings section (defaults to{}; absent config is a no-op).autoflush_buffer.py: the timer and flush threads are nowdaemon=True, so a process can exit even ifstop()was never reached..gitignore:core.*→core.[0-9]*so files likecore.pyare not ignored.6. Docs, examples, tests, CI
docs/agent_plugins.rst(+318),docs/harness_plugins.rst(+322),docs/agent.rstanddocs/index.rstupdates; regenerated OpenAPI spec; +275 lines of README.examples/agents/, one per plugin plus a combined multi-framework one.tests/harness/(12),tests/agents/plugins/andtests/agents/prov_analysis/(10),tests/adapters/test_diaspora.py. Coverage includes each capture source, cross-capture and cross-plugin linking, CLI, MCP server, plugin assets, and Flowcept interop.ruff==0.15.22inchecks.ymlandrun-tests.yml(unpinned ruff was changing formatting expectations between runs), and a new check that the committed OpenAPI spec matches what the code generates.pyproject.toml: newharness_otel,harness_claude_sdk, anddiasporaextras.Backwards compatibility
No existing public API changed. Everything new is opt-in: plugins are off unless
plugins:is set, harness capture only runs when hooks/exporters are installed, and the new extras are not part of the default install. The only behavioral change to existing code paths is thedaemon=Trueon the autoflush threads.Testing
The plugins were exercised end-to-end against the real frameworks and a live Anthropic API key (commit
9d6d654a), and the CLI-harness profiles were validated by replaying recorded Gemini-profile sessions (commit2d827328). Tests that need network or vendor SDKs skip when the dependency or key is absent.Notes for reviewers
main, this branch reintroducespsutil_p.connections()intelemetry_capture.py(upstream06da889chad changed it tonet_connections()for Fix deprecated warning in telemetry_capture #155) and drops the# group_id: autoKafka comment fromsample_settings.yaml(upstreamfc138b5f). Both were carried in by the older Diaspora branch; happy to fix in this PR.diasporaextra uses a direct git reference (diaspora-stream-api @ git+https://…) and required[tool.hatch.metadata] allow-direct-references = true. PyPI rejects direct-URL dependencies in uploaded metadata, so this may break the release workflow that publishes on pushes tomain. Options: drop the extra from this PR, or gate it behind a non-published extra. Guidance welcome.