agent-orchestrator: add explainability provenance for all patterns (#744)

agent-orchestrator: add explainability provenance for all agent
patterns

Extend the provenance/explainability system to provide
human-readable reasoning traces for the orchestrator's three
agent patterns. Previously only ReAct emitted provenance
(session, iteration, conclusion). Now each pattern records its
cognitive steps as typed RDF entities in the knowledge graph,
using composable mixin types (e.g. Finding + Answer).

New provenance chains:
- Supervisor: Question → Decomposition → Finding ×N → Synthesis
- Plan-then-Execute: Question → Plan → StepResult ×N → Synthesis
- ReAct: Question → Analysis ×N → Conclusion (unchanged)

New RDF types: Decomposition, Finding, Plan, StepResult.
New predicates: tg:subagentGoal, tg:planStep.
Reuses existing Synthesis + Answer mixin for final answers.

Provenance library (trustgraph-base):
- Triple builders, URI generators, vocabulary labels for new types
- Client dataclasses with from_triples() dispatch
- fetch_agent_trace() follows branching provenance chains
- API exports updated

Orchestrator (trustgraph-flow):
- PatternBase emit methods for decomposition, finding, plan, step result, and synthesis
- SupervisorPattern emits decomposition during fan-out
- PlanThenExecutePattern emits plan and step results
- Service emits finding triples on subagent completion
- Synthesis provenance replaces generic final triples

CLI (trustgraph-cli):
- invoke_agent -x displays new entity types inline
This commit is contained in:
cybermaggedon 2026-03-31 12:54:51 +01:00 committed by GitHub
parent e65ea217a2
commit 7b734148b3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 560 additions and 82 deletions

View file

@ -13,6 +13,11 @@ from trustgraph.api import (
Question,
Analysis,
Conclusion,
Decomposition,
Finding,
Plan,
StepResult,
Synthesis,
AgentThought,
AgentObservation,
AgentAnswer,
@ -209,6 +214,35 @@ def question_explainable(
if entity.observation:
print(f" Observation: {entity.observation}", file=sys.stderr)
elif isinstance(entity, Decomposition):
print(f"\n [decompose] {prov_id}", file=sys.stderr)
for i, goal in enumerate(entity.goals):
print(f" Thread {i}: {goal}", file=sys.stderr)
elif isinstance(entity, Finding):
print(f"\n [finding] {prov_id}", file=sys.stderr)
if entity.goal:
print(f" Goal: {entity.goal}", file=sys.stderr)
if entity.document:
print(f" Document: {entity.document}", file=sys.stderr)
elif isinstance(entity, Plan):
print(f"\n [plan] {prov_id}", file=sys.stderr)
for i, step in enumerate(entity.steps):
print(f" Step {i}: {step}", file=sys.stderr)
elif isinstance(entity, StepResult):
print(f"\n [step-result] {prov_id}", file=sys.stderr)
if entity.step:
print(f" Step: {entity.step}", file=sys.stderr)
if entity.document:
print(f" Document: {entity.document}", file=sys.stderr)
elif isinstance(entity, Synthesis):
print(f"\n [synthesis] {prov_id}", file=sys.stderr)
if entity.document:
print(f" Document: {entity.document}", file=sys.stderr)
elif isinstance(entity, Conclusion):
print(f"\n [conclusion] {prov_id}", file=sys.stderr)
if entity.document: