
Iii Architecture Patterns
- 1.3k installs
- 18.6k repo stars
- Updated August 5, 2026
- iii-hq/iii
iii-architecture-patterns is an agent skill that helps developers choose and apply iii architecture patterns—durable workflows, reactive backends, agentic pipelines, event-driven CQRS, effect pipelines, and trigger-trans
About
iii-architecture-patterns is an iii-hq agent skill for composing iii primitives into backend architectures when a task spans more than one function or trigger. It provides a pattern map that matches requirements to implementations: durable workflows via chained Functions and named queues with DLQ and step tracking; reactive backends; agentic pipelines; event-driven CQRS; effect pipelines; and trigger-transform-action automation using Workers, state, streams, and pub/sub. Developers reach for this skill when designing iii systems in TypeScript, Python, or Rust and need the correct shape before writing middleware or SDK calls. Use iii-core-primitives for Function, Trigger, and Worker basics and iii-sdk-reference for API details. The skill prevents one-off scripts where a queue-backed workflow or CQRS layout is the right fit.
- Recommended module boundaries in III
- Agent vs service separation patterns
- Event and workflow composition models
- Extension points for custom capabilities
- Anti-patterns to avoid in agent stacks
Iii Architecture Patterns by the numbers
- 1,330 all-time installs (skills.sh)
- +45 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #876 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/iii-hq/iii --skill iii-architecture-patternsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.3k |
|---|---|
| repo stars | ★ 18.6k |
| Last updated | August 5, 2026 |
| Repository | iii-hq/iii ↗ |
How do you choose iii architecture patterns for backend features?
Choose and apply III architecture patterns for modular agents, services, and data flow before implementing features in the iii-hq/iii codebase.
Who is it for?
Backend developers architecting multi-step iii features who must choose between workflows, reactive backends, CQRS, or agentic pipelines before coding.
Skip if: Single-function edits or SDK syntax lookups where iii-core-primitives or iii-sdk-reference alone suffice.
When should I use this skill?
The user designs durable workflows, reactive backends, agent pipelines, CQRS, or trigger-transform-action flows on the iii stack.
What you get
Selected iii pattern blueprint with Functions, Triggers, Workers, queues, streams, and state wiring
- Architecture pattern selection
- iii component wiring plan
By the numbers
- Covers 6 architecture patterns in the requirement-to-pattern map
- Uses 3 core iii primitives: Function, Trigger, Worker
Files
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
| Requirement | Pattern | iii shape |
|---|---|---|
| Sequential work with retries, DLQ, step tracking | Durable workflow | Functions chained through named queues, progress in state |
| Keep views, metrics, cache, or clients in sync | Reactive backend | State triggers plus stream/pubsub side effects |
| Specialized AI agents hand work to each other | Agentic backend | One function per agent, queue handoffs, shared state |
| Commands publish events and projections update independently | Event-driven CQRS | Command functions, event log in state, subscribe triggers |
| Pure, traceable composition | Effect pipeline | Small functions composed synchronously with trigger() |
| Webhook/cron automation chains | Low-code automation | Trigger, transform, action nodes chained by enqueue |
Durable Workflow
Use named queues when steps need different retry, FIFO, or concurrency policy.
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: [{ op: "set", path: `/steps/${step}`, value: 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
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": [{"op": "set", "path": f"/steps/{step}", "value": 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
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": [{ "op": "set", "path": "/steps/validate", "value": "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".
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.
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.
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 queue retry, FIFO, adapter, port, and worker-manager config, use
iii-engine-config. - For package-specific SDK syntax, use
iii-sdk-reference. - Worker-backed capability details live with the worker docs, not as top-level iii skills.
Related skills
FAQ
Which architecture patterns does iii-architecture-patterns cover?
iii-architecture-patterns covers six mapped shapes: durable workflows, reactive backends, agentic pipelines, event-driven CQRS, effect pipelines, and trigger-transform-action automation, each implemented with iii Functions, Triggers, Workers, queues, streams, and pub/sub.
When should I use iii-architecture-patterns versus iii-core-primitives?
Use iii-architecture-patterns when the task spans multiple functions, triggers, or data flows. Use iii-core-primitives first to learn Function, Trigger, and Worker basics before selecting a multi-step pattern.