4+1 Process View¶
The Process View captures what FCC does at runtime. Where the Logical View focuses on static class structure, this page traces control and message flow: how a workflow step becomes an LLM call, how external tools invoke FCC via MCP, how two agents negotiate A2A capabilities, and how the compliance auditor runs as an out-of-band job. Every diagram on this page is a live sequence — reading them top- to-bottom shows a single execution trace.
Four diagrams follow: the Find to Create to Critique cycle, the MCP inbound call, an A2A agent card exchange, and a compliance audit run.
Find, Create, Critique cycle¶
The spine of the framework. SimulationEngine.run(start_node, payload)
at src/fcc/simulation/engine.py:50 walks a WorkflowGraph one node at
a time. For each node it resolves the persona and action, builds a
prompt via the ActionEngine, calls the configured AIClient,
validates the output, records a turn, and publishes one
workflow.step event on the EventBus. A single workflow.completed
event fires at the end.
Figure 1 traces a single end-to-end workflow run from the caller's perspective.
sequenceDiagram
participant Caller
participant SimulationEngine
participant PersonaRegistry
participant ActionEngine
participant AIClient
participant EventBus
participant Observability
Caller->>SimulationEngine: run(start_node, payload)
loop for each node in graph
SimulationEngine->>PersonaRegistry: by_id(persona_id)
PersonaRegistry-->>SimulationEngine: PersonaSpec
SimulationEngine->>ActionEngine: get_action_prompt(persona, action)
ActionEngine-->>SimulationEngine: {system, user}
SimulationEngine->>AIClient: complete(system, user)
AIClient-->>SimulationEngine: raw_output
SimulationEngine->>EventBus: publish(workflow.step)
EventBus-->>Observability: span emit
end
SimulationEngine->>EventBus: publish(workflow.completed)
SimulationEngine-->>Caller: MessageHistory
MCP inbound persona lookup¶
When an external tool (a CrewAI agent, an IDE extension, etc.) invokes
FCC over MCP, the MCPServer at src/fcc/protocols/mcp/server.py
receives a JSON-RPC request, resolves the tool name to a handler, and
returns a structured result. The stream_manager multiplexes streaming
responses for long-running tool calls.
Figure 2 traces an MCP persona_lookup call end-to-end.
@startuml
actor "External Tool" as ET
participant "MCP Server" as MCP
participant "ToolRegistry" as TR
participant "PersonaRegistry" as PR
participant "StreamManager" as SM
ET -> MCP : JSON-RPC persona_lookup(id)
MCP -> TR : resolve("persona_lookup")
TR --> MCP : handler
MCP -> PR : by_id(id)
PR --> MCP : PersonaSpec
MCP -> SM : open_stream(request_id)
MCP --> ET : initial ack
MCP -> SM : send(persona_card)
SM --> ET : chunk
MCP -> SM : close(request_id)
SM --> ET : end
@enduml
The MCP bridge is thin by design: handlers call the same Python APIs the CLI would, so there is no duplicate business logic.
A2A agent card exchange¶
Two FCC personas running in different processes can negotiate
capabilities via the A2A protocol. The A2AServer at
src/fcc/protocols/a2a/server.py exposes an agent card that declares
skills; the client persona reads the card, finds a compatible skill,
and invokes it.
Figure 3 shows a capability negotiation between a Research Crafter (RC) and a Blueprint Crafter Champion (BCHM).
sequenceDiagram
participant RC as Research Crafter (client)
participant BCHM as Blueprint Crafter Champion (server)
participant CardStore as AgentCardStore
RC->>BCHM: GET /.well-known/agent.json
BCHM->>CardStore: load_card()
CardStore-->>BCHM: AgentCard(skills)
BCHM-->>RC: AgentCard
RC->>RC: match(needed_skill, card.skills)
RC->>BCHM: POST /skill/blueprint_draft
BCHM->>BCHM: validate_against_riscear()
BCHM-->>RC: SkillResult
RC->>RC: record_collaboration_edge()
The collaboration edge that RC records feeds back into the
cross-reference matrix at src/fcc/personas/cross_reference.py.
Compliance audit run¶
ComplianceAuditor.audit() is a batch job: given a PersonaRegistry,
it enumerates every persona, classifies each against the EU AI Act risk
tiers, runs all applicable quality gates, and assembles a
ComplianceReport. The CompliancePipeline wraps the audit with event
emission so dashboards and subscribers can react.
Figure 4 is a PlantUML activity diagram of one audit pass.
@startuml
start
:Load PersonaRegistry;
:Load RequirementRegistry (256+ EU AI Act, 29 NIST);
:Load 58 QualityGates;
while (more personas?) is (yes)
:Pick next persona;
:AIActClassifier.classify(persona);
:Select applicable requirements;
while (more gates?) is (yes)
:Evaluate gate;
if (pass?) then (yes)
:record pass;
else (no)
:record AuditFinding;
endif
endwhile
:emit compliance.persona_audited;
endwhile (no)
:Assemble ComplianceReport;
:Build EvidenceGraph;
:emit compliance.audit_completed;
stop
@enduml
How the async story fits together¶
The simulation engine is synchronous inside its loop; the
concurrency seam is the event bus. EventBus.publish at
src/fcc/messaging/bus.py:102 enqueues onto a bounded
queue.Queue and returns immediately. Subscribers drain the queue on a
worker thread pool; each subscriber has its own dead-letter queue
(src/fcc/messaging/dlq.py) so a slow or failing subscriber cannot
back-pressure the publisher. The MCP and A2A servers run on separate
event loops and interact with the engine only through published events
and direct Python calls — they never reach into engine state. The
compliance pipeline runs detached from any live simulation, but its
events land on the same bus so the dashboard can surface audit
progress alongside live workflow steps.
That separation is the process-view invariant: the workflow critical path is synchronous and deterministic, while everything else (observability, protocol bridges, compliance reactions) rides the bus asynchronously.
See also¶
src/fcc/simulation/engine.py:50—SimulationEngine.runsrc/fcc/workflow/action_engine.py:51—ActionEngine.runsrc/fcc/messaging/bus.py:102—EventBus.publishsrc/fcc/protocols/mcp/server.py— MCP handler dispatchsrc/fcc/protocols/a2a/server.py— A2A agent card serversrc/fcc/compliance/pipeline.py—CompliancePipeline- Sequence diagrams deep-dive