Skip to content

Running Your First Workflow Action

The FCC framework defines a 6-action-type system that describes what any persona can do. Actions are orthogonal to the workflow graph (which describes when personas act). This tutorial walks you through loading actions, selecting a persona, and executing an action via the ActionEngine.

The Six Action Types

Every persona can perform up to six action types, defined by the WorkflowActionType enum:

Action Type Purpose
scaffold Generate new artifacts from scratch following best practices and governance requirements
refactor Improve and modernize existing artifacts while preserving correctness
debug Diagnose and fix issues, identifying root causes and providing corrective actions
test Validate quality by generating comprehensive test suites with edge-case coverage
compare Evaluate alternatives by analyzing trade-offs across performance, cost, and compliance
document Generate comprehensive documentation including purpose, usage, and architecture

Actions vs. Workflows

Actions describe capabilities -- what a persona can do. Workflows describe sequences -- the order in which personas are activated. A persona might be activated at a workflow node and then execute a scaffold action to produce its deliverable.

Loading Actions from YAML

Actions are defined in YAML files under data/personas/actions/. Each file contains action definitions for one or more personas.

from fcc.workflow.actions import WorkflowActionRegistry, WorkflowActionType

# Load actions from a single YAML file
registry = WorkflowActionRegistry.from_yaml("src/fcc/data/personas/actions/core.yaml")

# Or load all actions from a directory
registry = WorkflowActionRegistry.from_yaml_directory("src/fcc/data/personas/actions/")

# Inspect what was loaded
print(f"Total actions: {len(registry)}")
print(f"Personas with actions: {registry.persona_ids}")
print(f"Action types available: {[t.value for t in registry.action_types]}")

Expected output:

Total actions: 204
Personas with actions: ['AMS', 'BC', 'BCHM', 'BV', 'CIA', ...]
Action types available: ['compare', 'debug', 'document', 'refactor', 'scaffold', 'test']

Querying Actions

The WorkflowActionRegistry supports lookup by persona, by action type, or by a specific combination:

# Get all actions for the Research Crafter
rc_actions = registry.for_persona("RC")
for action in rc_actions:
    print(f"  {action.action_type.value}: {action.description[:60]}...")

# Get all scaffold actions across all personas
scaffold_actions = registry.for_type(WorkflowActionType.SCAFFOLD)
print(f"\nScaffold actions: {len(scaffold_actions)} personas")

# Get a specific action
action = registry.get("RC", WorkflowActionType.SCAFFOLD)
print(f"\nRC scaffold: {action.description}")
print(f"  Steps: {len(action.execution_steps)}")
print(f"  Inputs: {list(action.inputs)}")
print(f"  Outputs: {list(action.outputs)}")

Setting Up the ActionEngine

The ActionEngine connects personas, actions, and (optionally) an AI client. In mock mode, it produces deterministic results without calling any external API:

from fcc.personas.registry import PersonaRegistry
from fcc.workflow.actions import WorkflowActionRegistry, WorkflowActionType
from fcc.workflow.action_engine import ActionEngine

# Load personas and actions
personas = PersonaRegistry.from_data_dir("src/fcc/data/personas")
actions = WorkflowActionRegistry.from_yaml_directory(
    "src/fcc/data/personas/actions/"
)

# Create the engine in mock mode (no AI client)
engine = ActionEngine(
    persona_registry=personas,
    action_registry=actions,
    ai_client=None,  # Mock mode
)

# List which personas have actions
available = engine.available_personas()
print(f"Personas with actions: {len(available)}")

Running an Action

Execute an action by specifying the persona ID and action type:

from fcc.workflow.actions import WorkflowActionType

result = engine.run("RC", WorkflowActionType.SCAFFOLD)

print(f"Persona: {result.persona_id}")
print(f"Action: {result.action_type.value}")
print(f"Success: {result.success}")
print(f"Mode: {result.metadata.get('mode')}")
print(f"\n{result.content}")

Expected output:

Persona: RC
Action: scaffold
Success: True
Mode: mock

[Mock scaffold result for Research Crafter]

Action: Generate new research briefs from source materials...
Persona: Research Crafter (RC)
Steps: 5
Inputs: 3
Outputs: 4

Passing Custom Inputs

You can supply additional context via the inputs parameter:

result = engine.run(
    "BC",
    WorkflowActionType.DOCUMENT,
    inputs={
        "project": "Payment Gateway",
        "scope": "Architecture decision records",
        "audience": "Senior engineers",
    },
)
print(f"Success: {result.success}")
print(f"Content preview: {result.content[:200]}")

Connecting to the Event Bus

The ActionEngine integrates with the FCC event bus to emit lifecycle events. This enables observability and cross-system coordination:

from fcc.messaging.bus import EventBus
from fcc.messaging.events import EventType

bus = EventBus()

# Track action events
events_received = []
bus.subscribe(lambda e: events_received.append(e))

# Create engine with event bus
engine = ActionEngine(
    persona_registry=personas,
    action_registry=actions,
    event_bus=bus,
)

result = engine.run("DE", WorkflowActionType.TEST)
print(f"Events emitted: {len(events_received)}")
for event in events_received:
    print(f"  {event.event_type.value}: {event.payload}")

Expected output:

Events emitted: 2
  action.started: {'persona_id': 'DE', 'action_type': 'test'}
  action.completed: {'persona_id': 'DE', 'action_type': 'test', 'mode': 'mock'}

Understanding Action Prompts

When an AI client is configured, the engine builds persona-aware prompts. You can inspect these prompts without running the action:

from fcc.workflow.action_engine import get_action_prompt

persona = personas.get("RC")
action = actions.get("RC", WorkflowActionType.SCAFFOLD)
prompts = get_action_prompt(persona, action)

print("=== System Prompt (first 300 chars) ===")
print(prompts["system"][:300])
print("\n=== User Prompt ===")
print(prompts["user"][:300])

The system prompt includes the persona's R.I.S.C.E.A.R. specification (role, archetype, style, constraints), the action preamble, and any constitution rules from the persona's doc_context. The user prompt contains the execution steps, required inputs, and expected outputs.

Next Steps