Files
magnus919_agent-skills/llamaindex/references/workflows.md
T
Magnus Hedemark 3e86349539 feat: add llamaindex — expert skill for LlamaIndex framework
Comprehensive skill covering:
- Core architecture (7 primitives, Settings, data flow)
- RAG strategies (basic through advanced with hybrid retrieval, reranking)
- Multi-agent orchestration (AgentWorkflow, handoff bug fix)
- Event-driven workflows (durable execution, checkpoint/resume)
- Production deployment (llama-deploy, debugging, observability)
- PropertyGraphIndex (knowledge graphs, hybrid retrieval)
- Evaluation and span-attached observability
- Integration ecosystem (vector stores, LlamaHub, LlamaParse)

9 reference files, 4 templates, 1 verification script.
MIT licensed. 100% AI agent portable (no platform-specific content).

Signed-off-by: Magnus Hedemark <magnus919@pm.me>
2026-07-09 13:32:53 -04:00

2.7 KiB

LlamaIndex Workflows

Core Model

Workflows are event-driven step-based orchestration. Steps consume typed events and emit typed events.

from llama_index.core.workflow import Workflow, StartEvent, StopEvent, Event, step

class MyWorkflow(Workflow):
    @step
    async def step_one(self, ev: StartEvent) -> MyEvent:
        # Do work
        return MyEvent(result=processed_data)

    @step
    async def step_two(self, ev: MyEvent) -> StopEvent:
        # Final step
        return StopEvent(result=ev.result)

Running a Workflow

w = MyWorkflow(timeout=60, verbose=False)
result = await w.run(input_data="your data")

Control Flow Patterns

Pattern Implementation
Sequential Step A >> Event >> Step B
Branching if condition: return EventX else: return EventY
Looping Step returns event handled by an earlier step
Parallel fan-out return list[Event]
Parallel fan-in Accept list[Event]
Dynamic emission ctx.send_event(ev)
Dynamic collection ctx.collect_events(...)

State Management

async with ctx.store.edit_state() as state:
    state["counter"] = state.get("counter", 0) + 1

Durable Workflows (Checkpoint/Resume)

# Checkpoint on step completion
async for ev in handler.stream_events(expose_internal=True):
    if isinstance(ev, StepStateChanged) and ev.step_state == StepState.NOT_RUNNING:
        db.save("my-run", json.dumps(handler.ctx.to_dict()))

# Resume after crash
ctx = Context.from_dict(w, json.loads(db.load("my-run")))
result = await w.run(ctx=ctx)

Key properties:

  • At-least-once semantics (in-flight steps may re-run)
  • Step side effects must be idempotent
  • Non-serializable objects (API clients, DB connections) go in Resource factories

Resource Injection

from typing import Annotated
from llama_index.core.workflow import Resource

def get_client() -> MyApiClient:
    return MyApiClient()

class MyWorkflow(Workflow):
    @step
    async def process(self, ev: StartEvent,
                      client: Annotated[MyApiClient, Resource(get_client)]) -> StopEvent:
        result = await client.do_work(ev.data)
        return StopEvent(result=result)

Validation

workflow.validate()  # Check event graph before running
workflow.validate(validate_resources=True)  # Also resolves Resource factories

For intentionally dynamic steps: @step(skip_graph_checks=["reachability"])

Migrating from Query Pipelines

Query Pipelines are deprecated in 0.14+. Migrate patterns:

  • Loops in a DAG = a step returning an event consumed by an earlier step
  • Branches in a DAG = if/else returning different event types
  • Data passing in a DAG = typed event fields