Iii Architecture Patterns

by iii-hqf95eab270f73No license18K starsListed Oct 8, 2026Updated Oct 8, 2026Repository updated today

Use when composing iii primitives into backend architectures: durable workflows, reactive backends, agentic pipelines, event-driven CQRS, effect pipelines, and trigger-transform-action automation.

AI-generated overview

Guides selection and implementation of iii backend architecture patterns such as durable workflows, CQRS, and agentic pipelines.

What it does
This skill maps backend requirements to iii architecture patterns, including durable workflows, reactive backends, agentic backends, event-driven CQRS, effect pipelines, and trigger-transform-action automation. It provides a pattern map table, selection rules, and code examples in TypeScript, Python, and Rust showing how to compose iii primitives such as functions, triggers, workers, state, queues, streams, and pub/sub. It produces architectural guidance and implementation sketches rather than runnable artifacts.
When to use it
Use it when a task is larger than a single function or trigger and needs a complete backend pattern. It fits requests describing product behavior such as workflows, agentic systems, reactive apps, CQRS, effect pipelines, or automation chains. It is not for exact trigger configuration, engine configuration, or package-specific SDK syntax, which are covered by other skills.
Requirements
No scripts are shipped; it is instructions only. The examples assume the iii runtime and SDKs (iii-sdk for TypeScript, iii for Python, iii_sdk for Rust) and a running iii worker endpoint such as ws://localhost:49134.

Architecture Patterns

Use this skill when the task is larger than one function or trigger. Pick the pattern from the requirement, then implement it with Function, Trigger, Worker, state, queues, streams, and pub/sub.

Pattern Map

RequirementPatterniii shape
Sequential work with retries, DLQ, step trackingDurable workflowFunctions chained through named queues, progress in state
Keep views, metrics, cache, or clients in syncReactive backendState triggers plus stream/pubsub side effects
Specialized AI agents hand work to each otherAgentic backendOne function per agent, queue handoffs, shared state
Commands publish events and projections update independentlyEvent-driven CQRSCommand functions, event log in state, subscribe triggers
Pure, traceable compositionEffect pipelineSmall functions composed synchronously with trigger()
Webhook/cron automation chainsLow-code automationTrigger, transform, action nodes chained by enqueue

Durable Workflow

Use named queues when steps need different retry, FIFO, or concurrency policy.

TypeScript

typescript
import { registerWorker, TriggerAction } from "iii-sdk";
const iii = registerWorker("ws://localhost:49134", { workerName: "order-workflow" });
async function track(orderId: string, step: string, status: string) {  await iii.trigger({    function_id: "state::update",    payload: { scope: "orders", key: orderId, ops: [{ type: "merge", path: ["steps"], value: { [step]: status } }] },  });}
iii.registerFunction("orders::validate", async (order) => {  await track(order.id, "validate", "done");  return iii.trigger({    function_id: "orders::charge",    payload: order,    action: TriggerAction.Enqueue({ queue: "order-payment" }),  });});
iii.registerFunction("orders::charge", async (order) => {  await track(order.id, "payment", "done");  return iii.trigger({    function_id: "orders::ship",    payload: order,    action: TriggerAction.Enqueue({ queue: "order-ship" }),  });});

Python

python
from iii import register_worker
iii = register_worker("ws://localhost:49134")
def track(order_id, step, status):    iii.trigger({        "function_id": "state::update",        "payload": {            "scope": "orders",            "key": order_id,            "ops": [{"type": "merge", "path": ["steps"], "value": {step: status}}],        },    })
def validate(order):    track(order["id"], "validate", "done")    return iii.trigger({        "function_id": "orders::charge",        "payload": order,        "action": {"type": "enqueue", "queue": "order-payment"},    })
iii.register_function("orders::validate", validate)

Rust

rust
use iii_sdk::TriggerAction;use iii_sdk::protocol::TriggerRequest;use serde_json::json;
async fn enqueue_charge(iii: iii_sdk::IIIClient, order: serde_json::Value) -> Result<serde_json::Value, iii_sdk::Error> {    iii.trigger(TriggerRequest {        function_id: "state::update".into(),        payload: json!({            "scope": "orders",            "key": order["id"],            "ops": [{ "type": "merge", "path": ["steps"], "value": { "validate": "done" } }]        }),        action: None,        timeout_ms: None,    }).await?;
    iii.trigger(TriggerRequest {        function_id: "orders::charge".into(),        payload: order,        action: Some(TriggerAction::Enqueue { queue: "order-payment".into() }),        timeout_ms: None,    }).await}

Reactive Backend

Use state triggers when the requirement says "after create/update, do this", "avoid polling", or "push live updates".

typescript
iii.registerFunction("todos::on-change", async (event) => {  await iii.trigger({    function_id: "stream::send",    payload: { stream_name: "todos-live", group_id: "default", data: event.new_value },    action: TriggerAction.Void(),  });});
iii.registerTrigger({  type: "state",  function_id: "todos::on-change",  config: { scope: "todos" },});

Agentic Backend

Model each agent as a function with one responsibility. Store shared context in state and hand off work through named queues.

typescript
iii.registerFunction("agents::researcher", async (task) => {  await iii.trigger({    function_id: "state::set",    payload: { scope: "research", key: task.id, value: { findings: [] } },  });  return iii.trigger({    function_id: "agents::critic",    payload: task,    action: TriggerAction.Enqueue({ queue: "agent-tasks" }),  });});

Event-Driven CQRS

Commands validate and publish domain events. Projections subscribe independently and write query-optimized state.

typescript
iii.registerFunction("cmd::add-inventory-item", async (input) => {  const event = { type: "inventory.item-added", itemId: input.itemId, quantity: input.quantity };  await iii.trigger({    function_id: "state::set",    payload: { scope: "inventory-events", key: `${Date.now()}-${input.itemId}`, value: event },  });  await iii.trigger({ function_id: "publish", payload: { topic: event.type, data: event } });  return { accepted: true };});
iii.registerTrigger({  type: "subscribe",  function_id: "proj::inventory-list",  config: { topic: "inventory.item-added" },});

Selection Rules

  • Use sync composition for short effect pipelines where the caller needs the final result.
  • Use enqueue for unreliable, slow, or must-complete steps.
  • Use pub/sub for independent fan-out where each subscriber can tolerate event-style delivery.
  • Use state triggers for derived views and side effects that should run automatically after writes.
  • Use cron triggers for scheduled maintenance and periodic starts.
  • Keep each function small enough to test independently.

When to Use

  • Use this skill for complete backend patterns: workflows, agentic systems, reactive apps, CQRS, effect pipelines, and automation chains.
  • Use this when the request describes product behavior rather than a single SDK API call.

Boundaries

  • For exact trigger config, function registration syntax, custom triggers, channels, and HTTP-invoked functions, use iii-core-primitives.
  • For engine ports, adapters, engine-owned workers, and RBAC (rbac-proxy), use iii-engine-config; queue retry and FIFO policy live with the queue worker's docs.
  • For package-specific SDK syntax, use iii-sdk-reference.
  • Worker-backed capability details live with the worker docs, not as top-level iii skills.

Source and attribution

Source:iii-hq/iiiinskills/iii-architecture-patternsat commitf95eab2

License: No license

Content belongs to its original authors. SourceWeft indexes it from a public repository.

Report or request removal