DEV Community

HyunKi Lee
HyunKi Lee

Posted on

Agentic Note Expansion: From Raw Ideas to App Specs

Agentic Note Expansion with Loops and Goals

Raw, fragmented notes captured on a mobile device are a common starting point for software projects. A developer might jot down a few lines about a data model, a user flow, or a specific business rule while away from their keyboard. However, translating these unstructured fragments into rigorous, actionable engineering artifacts usually requires hours of manual synthesis.

Traditional static templates and simple LLM prompts often fail at this task. They lack the context to resolve ambiguities, leading to generic outputs that do not reflect the original intent. To solve this, we must look at the problem through the lens of system design. By treating note expansion as an agentic workflow governed by closed-loop feedback and explicit goals, we can systematically transform raw input into structured user stories, data schemas, and screen-by-screen UX flows.

The Problem with Static Expansion

When a system attempts to expand a brief note using a single prompt-response cycle, it operates without a feedback loop. If the input is "build an offline-first task manager with sync," a static expansion might generate a standard todo-list schema. It misses the critical engineering questions: What is the conflict resolution strategy? How are binary assets handled offline? What is the sync protocol?

Without a mechanism to identify missing information, the system either makes assumptions that are often incorrect or produces high-level platitudes. To build a reliable tool, the system must be able to:

  1. Analyze the input against a defined target schema.
  2. Identify gaps in the logic or requirements.
  3. Formulate specific queries or sub-tasks to resolve those gaps.
  4. Execute iterative refinement loops until the output meets a quality threshold.

This is the core of agentic note expansion.

The Architecture of a Closed-Loop Expansion System

To implement this, we design a system composed of three main components: the Planner, the Executor, and the Evaluator. This classic agentic triad operates over a shared state, executing a loop until a pre-defined goal is satisfied.

+-------------------------------------------------+
|                  Shared State                   |
|  (Raw Input, Current Artifacts, Gap Registry)   |
+-------------------------------------------------+
       ^                       |               ^
       |                       v               |
+--------------+       +--------------+       +--------------+
|   Planner    | ----> |   Executor   | ----> |  Evaluator   |
| (Finds Gaps) |       | (Drafts Spec)|       | (Checks Goal)|
+--------------+       +--------------+       +--------------+
Enter fullscreen mode Exit fullscreen mode

1. The Planner

The Planner reads the raw input and establishes the target goals. For a software feature, the goals might include a relational database schema, a set of OpenAPI specifications, and a step-by-step user flow. The Planner registers what information is missing from the initial note to complete these targets.

2. The Executor

The Executor is responsible for generating the actual content. It takes the current state and the Planner's instructions to write the markdown, SQL, or JSON specifications. It does not operate in a vacuum; it only addresses the specific gaps highlighted by the Planner.

3. The Evaluator

The Evaluator acts as an adversarial gatekeeper. It tests the generated artifacts against strict validation rules. For example, if the Executor generated a database schema, the Evaluator checks for foreign key integrity, missing indexes on frequently queried fields, and compliance with the offline-sync requirements. If validation fails, the Evaluator writes the failures back to the state as new gaps, and the loop repeats.

Implementing the Loop: A Pseudo-Code Implementation

The following pseudo-code demonstrates how to structure this iterative loop in an application. This pattern ensures that the system does not exit until the artifacts meet the defined quality criteria or the maximum iteration limit is reached.

class ExpansionState:
    def __init__(self, raw_note: str):
        self.raw_note = raw_note
        self.artifacts = {}
        self.detected_gaps = []
        self.iteration_count = 0

def expand_note_workflow(raw_note: str, max_iterations: int = 5) -> ExpansionState:
    state = ExpansionState(raw_note)

    # Initial planning phase
    state.detected_gaps = planner.analyze_initial_input(state.raw_note)

    while len(state.detected_gaps) > 0 and state.iteration_count < max_iterations:
        # Address the highest priority gaps
        active_gaps = state.detected_gaps[:3]

        # Executor drafts updates based on active gaps
        drafted_updates = executor.generate_specifications(state.artifacts, active_gaps)

        # Apply updates to the shared state
        state.artifacts.update(drafted_updates)

        # Evaluator reviews the updated state
        evaluation_result = evaluator.validate_artifacts(state.artifacts)

        # Update the gap registry with new or unresolved issues
        state.detected_gaps = evaluation_result.remaining_gaps
        state.iteration_count += 1

    if len(state.detected_gaps) > 0:
        # Log warnings if the system exited due to iteration limits
        logger.warning("Expansion completed with unresolved gaps", extra={"gaps": state.detected_gaps})

    return state
Enter fullscreen mode Exit fullscreen mode

Trade-offs and System Constraints

While this closed-loop methodology produces highly structured and technically sound specifications, it introduces specific trade-offs that system architects must consider.

Latency vs. Quality

A single-prompt generation takes seconds but often yields shallow results. A closed-loop system running multiple iterations can take significantly longer to complete. For asynchronous workflows, such as processing notes in the background after a user closes their mobile app, this latency is acceptable. For real-time interactive interfaces, the system must provide intermediate feedback to the user to maintain responsiveness.

Token Consumption and Cost

Iterative loops inherently consume more tokens. Each pass requires sending the current state, the generated artifacts, and the evaluation feedback back to the model. To mitigate this, the system should employ state-pruning techniques, passing only the relevant diffs and specific schemas rather than the entire project history on every iteration.

Loop Termination and Hallucination

There is a risk of the Planner and Evaluator entering an infinite loop if they disagree on a specific requirement. For instance, the Evaluator might flag a schema as incomplete, while the Executor lacks the context to resolve it without human input. Setting a strict iteration cap and implementing a fallback mechanism that flags the ambiguity for human review is essential for production stability.

The Path Forward for Developer Tooling

Moving beyond simple text completion requires building systems that understand intent, structure, and validation. By implementing agentic loops that treat note expansion as an engineering problem, we can turn fragmented thoughts into precise, production-ready specifications.

This approach forms the foundation of how we think about software planning and execution. This article is a preview of the kind of systems-thinking methodology Bridge will publish at launch.

Top comments (0)