Skip to content

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:50SimulationEngine.run
  • src/fcc/workflow/action_engine.py:51ActionEngine.run
  • src/fcc/messaging/bus.py:102EventBus.publish
  • src/fcc/protocols/mcp/server.py — MCP handler dispatch
  • src/fcc/protocols/a2a/server.py — A2A agent card server
  • src/fcc/compliance/pipeline.pyCompliancePipeline
  • Sequence diagrams deep-dive