QuestBoard: Turn Your Notion Workspace Into a Full RPG

This is a submission for the Notion MCP Challenge

See the generated workspace:
QuestBoard Notion

What I Built

QuestBoard turns a Notion page into a playable RPG-style productivity system.

Instead of giving you another flat task list, it creates a workspace where:

  • real tasks become quests
  • neglected areas become new quest targets
  • completed work turns into XP, levels, streaks, and achievements
  • bigger pressure points can become boss battles
  • weekly progress becomes a recap page written like a story chapter

The important part is that this is not just themed copy pasted into Notion. QuestBoard is MCP-native from end to end. It uses Notion MCP to create the workspace, create and update records, build hosted views, sync progression, log automation runs, and support review/correction loops.

Why It Is Useful

The core problem I wanted to solve was this: most productivity systems are good at storing work, but weak at making progress felt.

QuestBoard tries to make motivation, pressure, and momentum visible inside a workspace people already use:

  • weak skill areas are easier to spot
  • small wins still feel meaningful because they award progression
  • recurring inconsistency shows up as stale quests, not invisible drift
  • a user can review and correct generated content instead of treating AI output as automatically trusted

It also works beyond the canned showcase flow. A real user can onboard with:

  • a real goal
  • what success looks like
  • a real time budget
  • preferred pacing
  • constraints
  • motivation
  • optional domain context for niche tools or jargon

That profile is saved into Notion and used to shape future quests.

How A User Actually Gets Value

The real-user loop is:

  1. Connect hosted Notion MCP and point QuestBoard at a blank Notion page.
  2. Run guided onboarding so QuestBoard captures the user’s real goal, time budget, focus area, constraints, and motivation.
  3. QuestBoard creates the full workspace in Notion.
  4. The user works mostly in Notion: reviewing quests, moving them through status, and watching progression update.
  5. QuestBoard syncs XP, levels, streaks, skills, achievements, run logs, and review state.
  6. Weekly recaps and review workflows turn the workspace from “AI generated pages” into an operating system the user can keep using.

For ambiguous or niche goals, onboarding can optionally use Exa or Perplexity to ground the saved context before the first quests are generated.

What The Hosted MCP Path Creates

On the hosted path, QuestBoard creates 8 databases and 14 named views across 8 hosted view types.

Core databases:

  • Player Profile
  • Quest Board
  • Skill Trees
  • Achievement Log
  • Hero Roster
  • Adventure Recaps
  • Runs
  • Review Queue

Hosted views:

  • Hero Dashboard
  • Quest Ledger
  • Quest Map
  • Quest Calendar
  • Quest Timeline
  • Quest Cards
  • XP Progress
  • Skill Focus
  • Skill Board
  • Trophy Case
  • Hero Roster
  • Story Archive
  • Run Center
  • Review Queue

That is what makes the product feel like a real Notion system instead of a terminal tool that happens to write pages.

Video Demo

The video focuses on the strongest hosted path:

  • create the workspace on a blank Notion page
  • Questboard generated views and structure
  • Questboard do quest generation and progression
  • QuestBoard syncs Notion changes back into the game state

Show Us The Code

QuestBoard

Turn your Notion workspace into an RPG. QuestBoard is a Python app that uses Notion MCP to create and operate a gamified workspace with quests, boss battles, skill trees, XP, recaps, runtime automation, and human review workflows.

What It Does

  • Creates a full QuestBoard workspace inside Notion
  • Guides first-time setup with questboard onboard so a real goal, time budget, motivation, and constraints shape the workspace
  • Generates quests from your focus areas and skill gaps
  • Creates boss battles for neglected skills or habits
  • Tracks XP, leveling, streaks, and achievements
  • Writes weekly recaps with AI or deterministic fallbacks
  • Can optionally ground ambiguous goals with Exa or Perplexity before the first quests are generated
  • Logs automation runs in Runs
  • Routes generated output through a Review Queue
  • Supports revision loops for reviewed quests and recaps
  • Runs a policy-based runtime loop with questboard runtime and questboard watch

Notion MCP Integration

QuestBoard is MCP-native. Notion…

Key files:

File What it does
src/cli.py User-facing commands for setup, onboarding, doctor, sync, runtime, review, revision, and demo flows
src/setup_workspace.py Builds the Notion workspace, schemas, hosted views, and seed data
src/mcp_client.py MCP wrapper for hosted vs self-hosted Notion operations
src/onboarding.py Goal grounding, optional research, and context-brief generation
src/engines/quest_generator.py Quest generation, boss generation, JSON repair, and fallback templates
src/engines/xp_engine.py XP, leveling, streaks, achievements, and progression reconciliation
src/engines/recap_writer.py Weekly recap generation and stale quest patrol
src/runtime.py Policy-based runtime planning, watch mode, and recurring control-loop behavior
src/operations.py Review Queue operations and review-surface reconciliation
src/revision.py Correction-loop revision from review notes

Local validation for the release snapshot reached 130 passed.

How I Used Notion MCP

QuestBoard is built around Notion MCP, not lightly assisted by it.

Every important operation goes through MCP:

MCP capability How QuestBoard uses it
Create database Builds the full multi-database workspace
Create pages Creates quests, boss battles, recaps, player records, run logs, and review items
Update page Syncs quest status, XP, levels, streaks, and review state
Create view Builds the hosted product surfaces like Quest Map, XP Progress, Hero Dashboard, Run Center, and Review Queue
Search Finds player, quest, skill, run, and review records across the workspace
Fetch Reads schema and page state to drive generation, sync, and runtime decisions
Create comment Adds progression flavor, warnings, and operational commentary
Move pages Supports archival and organization flows

I also intentionally supported both hosted and self-hosted MCP paths:

  • hosted MCP is the strongest product/demo path because it can create the richer view suite
  • self-hosted MCP is still valuable for local validation and token-based setup

Reliability And Hardening

I spent a large part of the build on making the project less fragile:

  • questboard doctor provides a read-only workspace health check
  • questboard hosted-login makes the hosted OAuth path usable without hand-building tokens
  • setup accepts full Notion URLs, not just raw IDs
  • rerunning setup can repair an older saved workspace instead of blindly trusting stale local metadata
  • QuestBoard has deterministic fallback generation when model output is malformed or unavailable
  • generated content is reviewable, correctable, and revision-friendly through Review Queue and revision flows
  • Run Center records operational history instead of hiding it

That matters because an MCP project should not just generate a cool first page. It should keep behaving coherently once the workspace is alive.

Closing

QuestBoard is my attempt to make Notion feel less like a storage layer and more like a playable progression system.

The goal was not only to make something flashy. The goal was to make a workspace where motivation, progress, governance, and automation all become visible inside Notion itself.

Agentic Architectures — Article 2: Advanced Coordination and Reasoning Patterns

Solving the “Stochastic Parrot” Problem with Structured Logic

There’s a criticism of large language models that has stuck around since 2021, and it still stings a little: the “stochastic parrot” argument. The idea is that LLMs are sophisticated pattern-matchers that produce statistically plausible text without any genuine understanding behind it. They’re parroting, not reasoning.

I’m not here to settle that philosophical debate. What I am here to tell you is this: if your agentic system behaves like a stochastic parrot — confidently producing plausible-sounding but wrong answers, failing to backtrack when it hits a dead end, unable to break a hard problem into manageable pieces — the fix is almost never the model. It’s the architecture.

The difference between an agent that looks intelligent in a demo and one that stays intelligent in production comes down to coordination and reasoning patterns. How does your agent plan? How does it check its own work? How do multiple agents share what they know without drowning each other in JSON?

That’s what this article is about.

Dynamic Planning: From Static Chains to Hierarchical Thinking

The first generation of “agentic” products were really just dressed-up chains. You’d define a fixed sequence of LLM calls — summarize, then classify, then respond — and call it a pipeline. It worked for simple, predictable tasks. It fell apart the moment the real world showed up.

Real tasks are rarely linear. A user asking “research our top three competitors and draft a positioning document” doesn’t map cleanly to a fixed sequence of steps. The number of competitors might be two or five. Each competitor might require a different depth of research. The positioning document might need a complete rewrite after the research reveals something unexpected.

What you need is Hierarchical Planning  — a “Manager” agent that treats the task as a problem to be decomposed, not a script to be executed.

The pattern works like this:

User Task
    └── Manager Agent (Planner)
            ├── Sub-task A → Worker Agent 1
            ├── Sub-task B → Worker Agent 2
            └── Sub-task C → Worker Agent 3
                    └── Sub-sub-task C1 → Worker Agent 3a

The Manager receives the top-level goal and produces a structured plan — a list of sub-tasks with dependencies, assigned roles, and success criteria. Worker agents execute their assigned sub-tasks and report results back. The Manager synthesizes the results, evaluates whether the goal has been met, and either delivers the final output or replans if something went wrong.

The critical implementation detail that most tutorials skip: the plan must be a living document, not a frozen spec. If Worker Agent 2 comes back with an unexpected result — say, a competitor has already pivoted out of your market — the Manager needs to update the plan in response. A Manager that rigidly executes the original plan in the face of new information isn’t planning; it’s just executing a slightly fancier chain.

In practice, this means storing the plan in a mutable shared state that the Manager can read and rewrite between steps. LangGraph handles this elegantly with its state graph model. CrewAI has a more opinionated take with its hierarchical process mode. Both work — the choice depends on how much control you want over the graph structure (more on that shortly).

Fractal Chain-of-Thought: Reasoning That Zooms In

Standard Chain-of-Thought prompting — “think step by step before answering” — is one of the most reliable techniques for improving LLM reasoning quality. But it has a ceiling. For deeply complex problems, a flat sequence of reasoning steps runs out of resolution. The model is reasoning about the right things at the wrong granularity.

Fractal Chain-of-Thought (FCoT) addresses this by making reasoning recursive. When an agent encounters a sub-problem that is itself complex enough to warrant multi-step reasoning, it spawns a nested reasoning process rather than trying to resolve it in a single step.

Think of it like a zoom function. The top-level reasoning operates at the problem level:

Problem: Optimize our database query performance
  Step 1: Identify the slow queries
  Step 2: Analyze the execution plans
  Step 3: Propose index changes
  Step 4: Estimate performance impact

But Step 2 — “analyze the execution plans” — is itself a multi-step reasoning problem that deserves its own chain:

Sub-problem: Analyze execution plan for Query #7
  Step 2.1: Identify full table scans
  Step 2.2: Check join order efficiency
  Step 2.3: Evaluate predicate pushdown opportunities
  Step 2.4: Flag missing statistics

And Step 2.3 might zoom in further still.

The implementation is cleaner than it sounds. You give the agent a tool called something like deep_reason(sub_problem: str) -> str that recursively invokes the same reasoning architecture on the sub-problem. The result gets folded back into the parent reasoning chain. You set a maximum recursion depth (3-4 levels is usually plenty) to prevent infinite descent.

The payoff is significant for domains with nested complexity — legal analysis, systems debugging, financial modeling. The cost is proportionally higher token usage. FCoT is a targeted tool, not a default setting.

The Reflection Pattern: Building a Critic That Actually Criticizes

Here’s a failure mode that bites almost every team eventually: you implement a self-review step where the same model that generated an output also reviews it. The model gives itself a pass. Every time. The “reflection” becomes a rubber stamp.

This happens because LLMs are, to put it charitably, optimistic about their own work. The same statistical patterns that produced the original output will evaluate it favorably. You’ve built a conflict of interest into your architecture.

The fix is the Critic Pattern , and the key design principle is model diversity.

Generator (Model A) → Output → Critic (Model B) → Feedback → Generator → Revised Output

Using a different model for the critic role — Claude reviewing GPT-4o output, or Gemini reviewing Claude output — introduces genuine perspective diversity. Each model has different training data emphases, different failure modes, and different stylistic biases. A cross-model critic is far more likely to catch errors that the generator is systematically blind to.

The Critic agent should be given a structured evaluation rubric, not a vague “review this” prompt. A good rubric for a code-generating agent might look like:

  • Correctness : Does the code do what the spec requires?
  • Edge cases : Are null inputs, empty collections, and boundary values handled?
  • Security : Are there injection vectors, exposed secrets, or unsafe deserialization?
  • Readability : Would a mid-level engineer understand this without comments?
  • Test coverage : Are the happy path and at least two failure paths tested?

The Critic returns a structured response — pass/fail per criterion, plus specific feedback for each failure. The Generator receives this structured feedback and revises. This continues until all criteria pass or the maximum iteration count is reached.

One underrated implementation detail: give the Critic explicit permission to fail things. If your Critic prompt says “review this and suggest improvements,” you’ll get suggestions. If it says “your job is to find reasons this should not ship — be adversarial,” you’ll get a real review.

State Machines vs. DAGs: Choosing Your Control Flow Model

This is the question that causes more architecture debates than almost any other in the multi-agent space, and the answer is genuinely context-dependent.

Directed Acyclic Graphs (DAGs) model workflows that flow in one direction without cycles. Task A feeds into Task B and Task C; B and C feed into Task D; done. This is the natural model for pipelines where each step produces input for the next and you never need to revisit a completed step.

CrewAI’s sequential and hierarchical processes are essentially DAG-based. Temporal workflows are explicitly DAG-structured. They’re excellent for deterministic, well-understood workflows where the shape of the computation is known in advance.

Cyclic graphs (State Machines) allow loops — the ability to return to a previous state based on new information. This is what LangGraph was purpose-built for, and it’s the right model for any agent that needs to:

  • Retry a failed tool call with modified parameters
  • Return to a planning step after discovering the current plan won’t work
  • Run a reflection loop until quality criteria are met
  • Wait for human approval before proceeding

The decision rule I’ve converged on after shipping several production systems:

Does your agent ever need to go backwards?
                           / 
                         YES NO
                          | |
                     LangGraph CrewAI / Temporal
                  (cyclic graph) (DAG model)

“Going backwards” means any scenario where the correct next step depends on the outcome of a previous step in a way that might require revisiting earlier work. Reflection loops go backwards. Replanning goes backwards. Waiting for a human to approve and then resuming goes backwards.

If your workflow is genuinely linear — always the same steps, always in the same order, with no branching based on intermediate results — a DAG model is simpler and easier to reason about. But be honest with yourself about whether your workflow is actually linear or whether you’re just assuming it will be.

The infrastructure implications differ significantly:

                  DAG Model Cyclic / State Machine
-----------------------------------------------------------------------------------------------
Execution model Step functions / pipelines Long-running stateful process
State management Passed between steps Persisted in graph state store
Debugging Linear trace, easy to follow Requires full state inspection per node
Scalability Each step independently Entire graph runs in one execution context
Failure recovery Retry from last step Checkpoint and resume from last stable state
Cost predictability High (bounded steps) Lower (loop count is variable)

Shared Epistemic Memory: The Blackboard Architecture

Here’s a scaling problem that hits every team that gets beyond three or four agents: how do agents share what they know?

The naive approach is to pass everything as function arguments — the output of Agent A becomes the input to Agent B as a large JSON blob. This works until it doesn’t. The blob grows. Context windows fill up. You start seeing agents with 80% of their context window consumed by state they don’t actually need for their specific sub-task.

The sophisticated approach is the Blackboard Architecture  — a pattern borrowed from classical AI and distributed systems that is experiencing a quiet renaissance in the agentic era.

The concept is simple: instead of passing state between agents directly, all agents read from and write to a shared “blackboard” — a structured, queryable state store that sits outside any individual agent.

                        ┌─────────────────┐
                        │ BLACKBOARD │
                        │ (Shared State) │
                        └────────┬────────┘
                    ┌────────────┼────────────┐
                    ↓ ↓ ↓
              Agent A Agent B Agent C
            (reads/writes) (reads/writes) (reads/writes)

Each agent reads only the sections of the blackboard relevant to its current task. Each agent writes its outputs back to designated sections. No agent needs to know what other agents are doing — it just needs to know the schema of the blackboard.

In practice, the blackboard is typically implemented as:

  • A structured document in a database (DynamoDB, Redis, or Postgres with JSONB) for fast key-based access to specific state sections
  • A vector store for semantic retrieval when agents need to find relevant context without knowing the exact key
  • A message log for ordered history that agents can replay or summarize

The schema design of your blackboard is one of the most important architectural decisions you’ll make. Too flat and agents can’t find what they need without reading everything. Too nested and updates become complex. A layered approach works well: top-level sections for task metadata, agent outputs, shared knowledge, and execution history.

One design principle worth emphasizing: write provenance into every blackboard entry. Every piece of information written to the shared state should include which agent wrote it, when, and with what confidence level. When a downstream agent reads a fact and makes a decision based on it, you want to be able to trace that decision back to its source when something goes wrong.

Production Reality Check

The patterns in this article are genuinely powerful. They’re also genuinely expensive, and the cost compounds in ways that aren’t obvious until you’re staring at a cloud bill.

Let’s put some real numbers on it.

A Reflection loop that runs an average of 2 iterations doubles your model call count. If your base cost is $0.05 per task, reflection takes it to $0.10. That sounds manageable — until you’re handling 50,000 tasks per day, at which point reflection alone adds $2,500/day in model costs.

Fractal Chain-of-Thought with 3 levels of recursion and an average of 4 steps per level generates roughly 64 reasoning steps (⁴³) for a single complex query. At even modest token counts per step, this can push a single query cost into the $0.50–$2.00 range. Reserve it for problems that actually need that depth.

Cross-model Critic patterns (e.g., Claude reviewing GPT-4o) introduce a second API dependency with its own latency, rate limits, and cost curve. Budget for both. More importantly, test what happens when the Critic’s API goes down — your system should degrade gracefully, not grind to a halt.

The honest question to ask before adding any coordination pattern is: what’s the quality delta, and what’s it worth?

Reflection improving accuracy from 78% to 91% on a customer-facing recommendation engine that drives revenue? Worth the cost. Reflection improving accuracy from 94% to 96% on an internal summarization tool that saves analysts 10 minutes a day? Probably not.

Measure first. Add complexity second.

What Comes Next

In Article 3, we shift from how agents think to how agents fail — and more importantly, how you detect and recover from those failures before your users do.

AgentOps is the unglamorous but absolutely essential discipline of treating your AI system like the distributed system it actually is: with observability, guardrails, eval pipelines, and human checkpoints baked in from the start. Not bolted on after the first production incident.

Because there will be a production incident. There always is.

                  L1: Stateless L2: Tool-Augmented L3: Autonomous L4: Multi-Agent L5: Self-Correcting
------------------------------------------------------------------------------------------------------------------------------------------------------
Execution Serverless / Edge Serverless + integr. Long-running container Distributed orchestrator Distributed + feedback loops
State None None Short + long-term memory Shared state across agents State + mutation history
Latency profile Predictable Slightly variable Variable (loop-dependent) High, parallelizable Highest, bounded by budget
Cost model Linear (tokens) Linear + tool costs Nonlinear (calls per task) Nonlinear × agent count Nonlinear × iteration count
Primary failure Bad retrieval Tool hallucination Context overflow Cascade failures Runaway loops
Observability Basic logging Tool call tracing Full trace per loop Cross-agent tracing Cost + quality dashboards

Included for reference from Article 1 — the coordination patterns in this article map primarily to L3, L4, and L5.

This is Article 2 of a 4-part series on Agentic AI Architectures. Ready for Article 3 — AgentOps — whenever you are.

Stop Copying Skills Between Claude Code, Cursor, and Codex

This is part five in a series about wrangling the growing pile of skills, scripts, and context that AI coding agents depend on. In part one, I covered why progressive disclosure beats dumping everything into context. Part two showed how akm unifies your local assets across platforms into one searchable stash. Part three added remote context via OpenViking for teams. And part four plugged in community knowledge through Context Hub.

All of that assumed you were picking one tool. But you’re probably not. You’ve got Claude Code at work, Codex for side projects, Cursor for quick edits. Each one has its own skills directory — ~/.claude/skills/, ~/.codex/skills/, .cursor/rules/ — and none of them can see each other.

So you rebuild the same deploy skill twice. You forget where the good version of your testing scaffold lives. You copy files between directories and they drift within a week. You end up grepping across three different paths trying to find the one that handled database migrations correctly.

This isn’t a tooling problem. It’s a discovery problem. And in the past week alone, three separate products launched to fix it — a macOS GUI for browsing skill files, a web-based editor for organizing them, a designer’s viral Medium post about layered architecture for skills. People are clearly hurting here.

But every one of those solutions wants you to move your files somewhere. Copy them into a central location. Sync them between directories. Maintain one source of truth that you manually keep updated.

There’s a better approach: don’t move anything. Just make everything searchable.

Copy and Sync (The Obvious Way)

Pick a canonical directory, copy everything into it, keep it updated. Tools like ClaudeMDEditor make this easier with a GUI, and symlinks can automate some of it.

Works great — until it doesn’t. You update the original and forget to sync. The copy drifts. You end up with two versions of the same skill, slightly different, and no way to tell which is current. The maintenance overhead scales linearly with every new skill and every new platform.

GUI Discovery (The Pretty Way)

Tools like Chops give you a nice interface for browsing your skill files. You can see what’s where, organize them visually, tag them.

But your agent can’t use a GUI. When Claude Code is mid-task and needs a deployment skill, it can’t open an Electron app and browse around. It needs something it can call — a programmatic interface that returns results without human intervention.

Index in Place (The akm Way)

This is the approach akm takes. Don’t move your files. Don’t copy them. Don’t sync them. Just point at them and build an index.

Your skills stay exactly where each tool expects them. Claude Code still finds its skills in ~/.claude/skills/. Cursor still reads .cursor/rules/. Nothing breaks. But now there’s a single search layer across all of them.

When your agent needs something, it searches once and gets results from every source. When you update a skill in its original location, the index picks up the change. No sync step. No drift.

Five Commands and You’re Done

Here’s the full setup. Takes about 30 seconds.

# Install
curl -fsSL https://raw.githubusercontent.com/itlackey/akm/main/install.sh | bash

# Initialize
akm setup

# Point at your existing skill directories
akm add ~/.claude/skills
akm add ~/.codex/skills
akm add .cursor/rules

# Search across all of them
akm search "deploy"

That last command returns results from every source, ranked by relevance. Each result shows the asset type, name, source, and a snippet. Your agent — or you — can load the full content:

akm show skill:deploy-to-production

Only the skill you need gets loaded into context. Everything else stays out.

Tell Your Agent About It

Here’s the part that ties it all together. Drop this into your AGENTS.md, CLAUDE.md, or system prompt:

## Resources & Capabilities

Search for skills, commands, and knowledge using `akm search <query>`.
View full details with `akm show <ref>`.

That’s the entire integration. No plugins, no SDKs, no integration code. Any model that can run shell commands can use akm. Claude Code, Codex, Cursor — if it has a terminal, it works.

The agent runs akm search to find what it needs, akm show to load the content, and gets to work. Everything else stays out of context. Progressive disclosure — the agent discovers what exists, then activates only what it needs. If that pattern sounds familiar, I covered the architecture behind it in part one.

What’s Next

This post covered the individual developer workflow — one person, multiple tools, skills everywhere. But what happens when a team of five developers each has their own skills across three platforms? That’s where things get interesting, and where akm’s source model, Git integration, and private registry support come into play.

For now: install akm, point it at your directories, and run akm search. You’ll be surprised how many skills you already have.

Give it a look at github.com/itlackey/akm. If you’ve got agent assets scattered across platforms, give it a shot and let me know what breaks.

Agentic Architectures — Article 1: The Agentic AI Maturity Model

From “Just Call the API” to Self-Evolving Ecosystems

There’s a conversation I keep having with engineering teams. Someone has just shipped a feature that calls GPT-4o or Claude, the demo looks impressive, and then a product manager walks in and asks: “So when do we make it fully autonomous?”

The room goes quiet.

The problem isn’t ambition — it’s vocabulary. “Autonomous” means five completely different things depending on who’s in the room. To the CTO, it means cost savings. To the ML engineer, it means ReAct loops and tool-calling. To the backend team, it means a distributed system they’re going to have to debug at 2am.

What we need is a shared language. A maturity model.

I’ve spent the last two years building production AI systems — RAG pipelines, multi-agent orchestrators, agentic workflows running on cloud runtimes — and I’ve come to believe that every system you build sits at one of five levels. Knowing which level you’re on is the single most important thing you can do before making architectural decisions.

Let’s walk through all five.

Level 1: Prompt-Based — The Stateless

The signature move: You write a prompt. The model responds. Done.

This is where every team starts, and there’s no shame in it. A well-engineered Level 1 system — think basic RAG with a vector database, or a single-turn LLM call wrapped in a clean API — can handle an enormous amount of real business value. Customer FAQ bots, document summarization, code explanation tools: these are Level 1, and they work.

The architecture is simple because the state is zero. Each request is born and dies in a single HTTP round-trip. There’s no memory between turns, no planning, no tool use. The LLM is a sophisticated function: input goes in, text comes out.

User Query → [Context Retrieval] → Prompt → LLM → Response

Infrastructure fingerprint: A single serverless function (Lambda, Cloud Run) is often enough. Latency is predictable because you’re making exactly one model call. Cost is linear and easy to forecast. The main failure mode is retrieval quality — garbage in, garbage out — not the agent layer, because there is no agent layer.

Where it breaks: The moment a user wants the system to do something with the answer. “Summarize this contract” is Level 1. “Summarize this contract and then send the action items to our Jira board” is not.

Level 2: Tool-Augmented — The Doer

The signature move: The model decides which function to call, and your infrastructure executes it.

This is where things get genuinely interesting — and where a surprising number of teams stop, thinking they’ve “done AI.” Function calling (or “tool use” in Anthropic’s terminology) fundamentally changes the mental model. The LLM is no longer just generating text; it’s generating intent.

You define a set of tools — an OpenAPI spec, a Python function schema, a list of MCP-compatible endpoints — and the model figures out which ones to invoke based on the user’s request. Your code handles the execution and feeds the result back.

User Query → LLM (reasoning) → Tool Call → Execution → LLM (synthesis) → Response

What makes Level 2 non-trivial in production is error handling. Models hallucinate tool names. They pass arguments with wrong types. They call a write endpoint when they should have called a read one. A robust Level 2 system needs:

  • Input validation on every tool call before execution
  • Graceful fallbacks when a tool returns an error (don’t just crash — tell the model what went wrong and let it retry)
  • Idempotency checks on any tool that mutates state

The OpenAPI spec integration story is particularly powerful here. If you describe your internal APIs in OpenAPI format, you can essentially give the model a self-describing interface to your entire backend. This is the beating heart of products like Copilot for enterprise apps.

Infrastructure fingerprint: You’re now managing tool execution latency in addition to model latency. Two or three tool calls in sequence, each taking 200–500ms, can make a “fast” response feel slow. Start thinking about parallelizing independent tool calls. Cost starts to diverge from simple per-token math — a tool that calls a third-party API has its own cost curve.

Where it breaks: When the task requires multi-step reasoning across interdependent actions. The model can call tools, but it can’t hold a plan in its head across a long sequence of them. For that, you need state.

Level 3: Autonomous Agents — The Planner

The signature move: The ReAct loop. Reason, Act, Observe, repeat.

This is the architecture that the word “agent” was coined for. Introduced in the landmark 2022 paper ReAct: Synergizing Reasoning and Acting in Language Models, the core idea is elegantly simple: instead of a single prompt-response cycle, you give the model a loop.

Thought → Action → Observation → Thought → Action → Observation → ... → Final Answer

At each step, the model articulates its reasoning (“I need to check the user’s account balance before proceeding”), selects a tool, observes the result, and decides what to do next. The loop continues until the model decides it has enough information to respond.

What makes Level 3 qualitatively different from Level 2 is memory management. A ReAct agent needs to track what it’s done, what it’s learned, and what it still needs to do. This splits into two distinct concerns:

Short-term memory is the conversation context — the running thread of thoughts, actions, and observations that constitutes the current task. In practice, this is the LLM’s context window, and it’s finite. Naive implementations stuff everything into the context until it overflows. Sophisticated ones implement sliding windows, summarization, or structured scratchpads.

Long-term memory is everything the agent needs to remember across tasks — user preferences, learned facts, past decisions. This typically lives outside the model entirely: a vector database for semantic retrieval, a key-value store for structured facts, or a graph database for relational knowledge.

The combination of a reasoning loop and dual-layer memory is what gives Level 3 agents their apparent intelligence. They can decompose problems, backtrack when a tool call fails, and accumulate knowledge over a session in ways that feel remarkably human.

Infrastructure fingerprint: Now you’re operating a stateful, long-running process. Serverless functions with 30-second timeouts don’t cut it anymore. You need persistent execution environments — containerized long-running services, step function orchestrators, or purpose-built agent runtimes (AWS Bedrock AgentCore, Azure AI Foundry Agent Service). Token costs are no longer linear: a complex reasoning chain might make 8–12 model calls to answer one user query. Build cost monitoring from day one.

Where it breaks: A single agent with access to all tools is a single point of failure — and a single point of security exposure. When the task requires genuine parallelism or specialist expertise, one planner isn’t enough.

Level 4: Multi-Agent Orchestration — The Team

The signature move: Specialized agents with defined roles, coordinated by an orchestrator.

The intuition here maps cleanly to how human teams work. You don’t hire one person who is simultaneously a senior engineer, a QA lead, a security auditor, and a product manager. You build a team. Level 4 applies the same logic to AI.

A canonical software engineering multi-agent system might look like this:

  • Orchestrator Agent : Receives the task, breaks it into sub-tasks, routes work, and assembles the final output.
  • Coder Agent : Writes code given a spec. Has access to file system tools and a code execution sandbox.
  • Reviewer Agent : Reads code, applies a checklist, and returns structured feedback. Possibly runs on a different model for perspective diversity.
  • Tester Agent : Generates test cases, runs them against the code, and reports pass/fail.
  • Security Agent : Scans for common vulnerabilities (injection, exposed secrets) before the code is merged.

Each agent operates within a narrow, well-defined context. This matters for three reasons:

Reduced hallucination: A focused prompt with a specific role and limited tool access produces more reliable output than a general-purpose agent trying to do everything.

Parallelism: Independent sub-tasks can run concurrently. The Reviewer and Tester can work in parallel on the same code diff.

Accountability: When something goes wrong (and it will), you can isolate which agent in the pipeline failed and why. This is far easier than debugging a single monolithic agent’s 40-step reasoning trace.

The coordination layer is where the real engineering lives. You need to decide how agents communicate — direct calls, a message queue, a shared state store — and how to handle failures in one agent without cascading across the whole system. (More on this in Article 2.)

Infrastructure fingerprint: You are now running a distributed system. All of the distributed systems problems apply: network partitions, partial failures, ordering guarantees, idempotency. Your observability stack needs to trace requests across agents, not just within one. Tools like LangSmith or Arize Phoenix become essential, not optional. Compute costs grow non-linearly with agent count — a four-agent pipeline that each makes 5 model calls generates 20 model calls per user request.

Where it breaks: Quality drift. Multi-agent systems can converge on confidently wrong answers because each agent assumes the previous one got it right. No one is questioning the chain. That’s the job of Level 5.

Level 5: Self-Correcting Systems — The Optimizer

The signature move: Agents that critique their own output and update their own behavior.

This is the frontier — and the most misunderstood level. “Self-correcting” doesn’t mean the AI is rewriting its own weights (that’s training, not inference). It means the system has architectural mechanisms to catch its own errors and improve its outputs within a deployment.

The foundational pattern is Reflection. After an agent produces an output, a separate “Critic” agent (or a second pass of the same model with a different prompt) evaluates it against a rubric:

  • Does this answer the original question?
  • Are there factual claims that need verification?
  • Does the code actually compile and pass tests?
  • Is the tone appropriate for the context?

If the critic finds problems, the output goes back to the generator with structured feedback. The generator revises. The critic reviews again. This loop runs until the output passes — or until a maximum iteration count is hit (always set one; an infinite reflection loop is a runaway cost event).

The more advanced form of this is prompt mutation  — when an agent not only fixes its current output but also updates the prompt template that produced it, so future calls start from a better baseline. This is where you start to see systems that genuinely improve over time without retraining.

Generator → Output → Critic → [Pass] → Deliver
                             → [Fail] → Feedback → Generator (repeat)

Some teams implement this with dedicated frameworks (DSPy’s prompt optimization is a notable example). Others build it manually by storing “lessons learned” in long-term memory that gets injected into future prompts.

Infrastructure fingerprint: The cost profile becomes unpredictable in a way that requires active management. A single reflection loop doubles your model calls. Two loops quadruples them. You need circuit breakers — hard limits on loop iterations, cost caps per request, and alerting when a task is taking 3x the expected token budget. The compute requirement is also asymmetric: reflection runs well on smaller models (you don’t need GPT-4o to critique a GPT-4o output; Claude 3.5 Haiku reviewing a Sonnet output can work remarkably well and costs a fraction of the alternative).

Mapping Levels to Infrastructure

A quick reference for the architectural decisions that change at each level:

                  L1: Stateless L2: Tool-Augmented L3: Autonomous L4: Multi-Agent L5: Self-Correcting
------------------------------------------------------------------------------------------------------------------------------------------------------
Execution Serverless / Edge Serverless + integr. Long-running container Distributed orchestrator Distributed + feedback loops
State None None Short + long-term memory Shared state across agents State + mutation history
Latency profile Predictable Slightly variable Variable (loop-dependent) High, parallelizable Highest, bounded by budget
Cost model Linear (tokens) Linear + tool costs Nonlinear (calls per task) Nonlinear × agent count Nonlinear × iteration count
Primary failure Bad retrieval Tool hallucination Context overflow Cascade failures Runaway loops
Observability Basic logging Tool call tracing Full trace per loop Cross-agent tracing Cost + quality dashboards

Production Reality Check

Here’s the honest conversation you need to have before choosing a level: most production systems should be Level 2 or 3, and that’s not a failure.

I’ve seen teams build Level 4 multi-agent systems because it felt more impressive, only to discover that a well-engineered Level 2 system with good tool design would have answered 80% of the queries faster, cheaper, and with fewer failure modes.

The maturity model isn’t a ladder you’re supposed to climb as fast as possible. It’s a map. The right level is the one where the complexity you’re adding is justified by the capability you’re gaining.

Some honest benchmarks from production:

  • A Level 3 ReAct agent making 8 model calls to answer a single query costs roughly 8–15x more than a Level 1 RAG call. The accuracy improvement is real — but measure it against your actual use case, not a benchmark.
  • Adding a reflection loop (Level 5 element) to a Level 3 agent typically improves output quality by 15–30% on complex reasoning tasks. It also doubles latency and cost. For a customer-facing product with a 3-second SLA expectation, that tradeoff often doesn’t pass.
  • Multi-agent systems (Level 4) have an operational overhead that is consistently underestimated. Plan for it to take 3–4x longer to debug a failure in a 4-agent pipeline than in a single agent — not because the problem is harder, but because the trace is longer and the failure point is further from where the error surfaces.

What Comes Next

In the next article, we’ll go deeper into the coordination and reasoning patterns that make Level 3 and Level 4 systems actually work in practice — hierarchical planning, the Critic architecture, and the surprisingly important question of whether you should use a cyclic graph or a DAG to model your agent’s workflow.

The short answer is: it depends on whether your agent ever needs to go backwards. And the answer is almost always yes.

This is Article 1 of a 4-part series on Agentic AI Architectures. The series covers the Maturity Model, Coordination & Reasoning Patterns, AgentOps, and Agentic Protocols (MCP & A2A).

Reimagining Creativity: Inside IdeaForge

_In an era where the “blank page” is the biggest hurdle to innovation, the tools we use to brainstorm, organize, and refine our thoughts matter more than ever. Enter IdeaForge—a modern, full-stack solution designed to take ideas from a fleeting thought to a structured reality.

Whether you are a developer looking for inspiration, a writer battling blocks, or a strategist mapping out a new project, IdeaForge provides the “arena” to forge raw concepts into polished gems._

What is IdeaForge?

At its core, IdeaForge is an AI-powered content and idea management platform. Hosted at ideaforge-arena.vercel.app, it serves as a centralized hub where users can generate, store, and refine prompts and concepts.

The project aims to solve the problem of “context switching.” Instead of jumping between a notes app, an AI chat interface, and a document editor, IdeaForge integrates these workflows into a single, intuitive dashboard.

Key Features

1. AI-Powered Prompting

IdeaForge isn’t just a digital notebook. It leverages advanced AI models to help users craft high-quality, engaging prompts. By using the “Arena,” creators can explore imaginative prompts that are tailored for modern creative needs—be it for social media, coding, or storytelling.

2. The Content Vault

One of the most significant pain points for creators is losing track of a great idea. IdeaForge includes a robust “vault” system where you can save drafts, organize your thoughts, and keep your best prompts ready for deployment at any time.

3. Modern UI/UX

The first thing you’ll notice when visiting the live site is the sleek, responsive interface. Built with TypeScript and Tailwind CSS, the platform offers a “dark-mode” friendly, accessible experience that stays out of your way and lets your creativity take center stage.

4. Collaborative Sharing

Innovation rarely happens in a vacuum. IdeaForge is designed for the modern world, allowing users to not just create, but also share their imaginative prompts with a wider community, fostering a culture of collaborative growth.

The Tech Stack Behind the Magic

For the developers out there, the GitHub repository reveals a sophisticated architecture built for speed and scalability:

  • Frontend: Built with Next.js and React, ensuring fast load times and SEO-friendly pages.
  • Styling: Tailwind CSS provides a modular and beautiful design system.
  • Language: TypeScript is used throughout to ensure type safety and a more reliable codebase.
  • Deployment: The project is seamlessly hosted on Vercel, taking advantage of edge computing for global performance.

Why it Matters

The barrier to entry for content creation is lower than ever, but the noise is louder. Tools like IdeaForge are essential because they focus on quality and organization. By helping users “forge” better prompts, the resulting output—be it an article, a piece of code, or a marketing campaign—becomes significantly more effective.

Get Started

Ready to level up your creative workflow?

  • Try the App: Head over to IdeaForge Arena and start crafting.
  • Explore the Code: Check out the source code, contribute, or star the project on GitHub.

IdeaForge is more than just a tool; it’s a workspace for the next generation of thinkers. It’s time to stop scattered thinking and start forging.

Why Your SFTP Transfer Is Stuck at 2 MB/s (and the Fix Is a Protocol from 1983)

Two minutes to copy a 274 MB file to a VM running on localhost. Not over the internet. Not to a cloud instance across the country. Localhost. The same machine, loopback, zero network latency.

That was the experience a user reported in issue #290 on cubic, a lightweight CLI for managing QEMU/KVM virtual machines. The maintainer reproduced it, traced the problem to the upstream russh-sftp crate, and posted a comment asking if anyone had ideas about where the bottleneck was. I did. The answer turned out to be a protocol design decision that limits every Rust project using this crate to about 2 MB/s on file transfers, regardless of how fast the link is.

The fix was to stop using SFTP entirely and fall back to a simpler, older protocol.

What Is cubic?

cubic is a CLI tool for creating and managing lightweight virtual machines on Linux and macOS. Think of it as the middle ground between running Docker containers and spinning up full VMs in libvirt. You run cubic create myvm --image debian and get a cloud-init provisioned VM with SSH access, a dedicated disk, and port forwarding. cubic ssh myvm drops you into a shell. cubic scp file.tar.gz myvm:~/ copies files in. It’s about 7,000 lines of Rust, built on QEMU/KVM with cloud-init for provisioning.

Under 40 stars. The maintainer (rogkne) commits daily and reviews external PRs within hours.

The Snapshot

Project cubic
Stars ~37 at time of writing
Maintainer Solo developer, committing daily
Code health ~7,000 lines of clean Rust, 104 unit tests, clap + thiserror + tokio
Docs Good README, CONTRIBUTING.md with conventional commit rules
Contributor UX Fast reviews, specific feedback, merged shell completions PR in multi-round review
Worth using Yes, if you want lightweight VMs without libvirt’s complexity

Under the Hood

cubic has a clean layered architecture. CLI commands live in src/commands/ (one file per subcommand, clap with derive macros). Business logic lives in src/actions/. The instance model, serialization (TOML and YAML), and storage live in src/instance/. Image fetching and distro definitions live in src/image/. SSH and file transfer live in src/ssh_cmd/.

The dependency list is lean. Four crates handle the heavy lifting: russh for SSH connections, russh-sftp for file transfers, clap for CLI parsing, and reqwest for image downloads. Everything else is standard library or small utility crates. The Cargo.toml is not trying to be clever.

One pattern that caught my eye: the project is async internally (tokio, russh) but sync at the CLI boundary. An AsyncCaller struct wraps a tokio multi-threaded runtime and exposes a call() method that blocks on a future. Every command creates one, runs its async work through it, and returns a sync result. It’s simple and it works. No async bleeding into the CLI layer.

The image pipeline is solid. cubic fetches cloud images from distro mirrors, verifies SHA-256/SHA-512 checksums against the upstream checksum file, shows a progress bar during download, and caches images locally. Adding a new distro means adding one entry to the DISTROS static in image_factory.rs. Rocky Linux was added in a recent PR following this exact pattern.

The rough edges are in the SSH layer. The SFTP implementation delegates to russh-sftp, which turned out to be the source of the performance bug. The progress bar during file transfers is coupled to the async read wrapper (AsyncTransferView), which works but makes it hard to swap the underlying transfer mechanism without touching the view layer. The test coverage is good for models and serialization but thin for the SSH and QEMU interaction code, which is typical for tools that depend on external services.

The Contribution

The performance issue (#290) reported that cubic scp transferred files at roughly 2 MB/s on loopback. I dug into the russh-sftp internals to find out why.

The answer is in how russh-sftp implements AsyncWrite. Every call to poll_write() creates a one-shot channel, sends an SFTP write request, and blocks until the server responds with an acknowledgment. One write in flight at a time. No pipelining. The SFTP protocol (RFC 4253) explicitly supports pipelining: clients can send many write requests with different IDs and collect the responses asynchronously. OpenSSH’s sftp client does exactly this with 64 outstanding requests by default. russh-sftp doesn’t. The upstream issue (#70) has been open since June 2025 with no fix.

For a 274 MB file at the default 255 KB max write size, that’s roughly 1,075 round-trips, each waiting for an ACK. Even on loopback, the per-request overhead adds up to minutes.

Wrapping the writer in a BufWriter wouldn’t help. It coalesces small writes into larger ones, but each poll_write() still blocks on the ACK. You’d go from many small round-trips to fewer large ones, but the bottleneck is the same.

The fix was to bypass SFTP for single-file transfers and use SCP instead. SCP is a much simpler protocol: open an SSH exec channel with scp -t <path>, send a one-line header (C0644 <size> <filename>n), stream the raw bytes, send a null byte, done. No request IDs, no per-packet ACKs during data transfer. Just a header and a byte stream.

I added a new scp.rs module (~170 lines) that implements SCP upload and download over a raw russh channel via channel.into_stream(). The async_copy function in russh.rs now detects single-file host-to-guest transfers and routes them through SCP. Directory copies and guest-to-guest transfers still use SFTP. Guest-to-host tries SCP first and falls back to SFTP if it fails (which it will for directories).

The review was thorough. The maintainer requested eight changes, all cleanups: use BufReader.read_line() instead of byte-by-byte loops, add error message prefixes, reuse the ack-reading function in the download path, validate the end-of-transfer marker byte. All reasonable, all addressed. He also asked (politely) whether the PR was AI-generated. I explained my workflow and he was satisfied. The PR went through two review rounds over 12 days and merged. PR #311.

The Verdict

cubic is for developers who want lightweight VMs without the weight of libvirt or the constraints of Docker. If you’re testing deployment scripts, need an isolated Linux environment for a project, or just want to spin up a Debian box and SSH into it without thinking about Vagrant files, this does the job.

The project is young (v0.19.0, solo maintainer) but the trajectory is good. New distros get added regularly. The contributor experience is above average: specific review feedback, no ego, merged with thanks. The maintainer is clearly using this tool daily and fixing things as they surface.

What would push cubic to the next level? The SFTP performance fix helps, but the bigger opportunity is user experience. A cubic init that scaffolds a project config file, better error messages when QEMU isn’t installed, and a Homebrew formula for macOS users would all lower the barrier. The foundation is clean. It just needs more people kicking the tires.

Go Look At This

If you manage VMs from the command line, try cubic. cubic create myvm --image debian and you’re running in under a minute. If you’ve been burned by slow file transfers to VMs before, the SCP fix in PR #311 is worth a look for the protocol analysis alone.

Star the repo. The codebase is small enough to read in a sitting, and there are open issues at every difficulty level.

This is Review Bomb #8, a series where I find under-the-radar projects on GitHub, read the code, contribute something, and write it up. If you know a project that deserves more eyeballs, drop it in the comments.

Nuxt Test Utils v4: Vitest v4 Requirement, Mocking Overhaul and Stricter Environment Setup

Nuxt Test Utils has released version 4.0.0, which primarily integrates Vitest v4. This update changes the test environment setup to beforeAll, resolving issues with module-level mocks. It also improves mockNuxtImport for cleaner partial mocking and enhances state management for registered endpoints. The library remains vital for testing in the Nuxt framework, bridging unit and end-to-end testing.

By Daniel Curtis

TUA Astro Hackathon'da final heyecanı başladı

Türkiye Uzay Ajansı öncülüğünde düzenlenen TUA Astro Hackathon, 37 şehirden 6 bine yakın katılımcının projelerini uzay ve havacılık alanında sunmasıyla başladı. Kazanan takımlara yatırım fırsatları ve destek verilecek.