Skip to content

Foundation

Welcome to the morning session of the Agentic Software Development workshop.

In this workshop, you'll build a client-side meeting tool called "HyperBytes".

Along the way, we'll explore the core disciplines of Spec-Driven Development (SDD) using the OpenSpec (OPSX) workflow, as well as creating the necessary guardrails and tooling for the agent to ensure high quality output.

Before You Begin

Before moving on to the guide, please carefully read through the following information.

What is OpenSpec?

Spec-Driven Development separates Intent (what to build) from Implementation (how to build it). Rather than coding directly, you direct an AI agent to build it for you.

OpenSpec is a Spec-Driven Development framework. You can find more information about it in their GitHub repository, but below is the most important information.

OpenSpec Changes

To provide the agent with enough information to correctly implement a feature, OpenSpec generates a "change" which consists of several files in a self-contained change folder under openspec/changes/[change-name]/. It contains four core planning artifacts that capture the What, Why, and How of the change:

  • proposal.md: Captures high-level intent, scope, and functional approach (the "Why" and "What").
  • specs/: Contains delta specifications (requirements and concrete scenarios in GIVEN/WHEN/THEN format) defining the exact behavioral changes. These are deltas because they describe how the application's specs should change.
  • design.md: Details the technical approach, architectural decisions, data flows, and files to modify (the "How").
  • tasks.md: An implementation checklist of checkboxes that the agent will execute step-by-step when the agent implements the change.

Note that these artifacts will move to an archive folder after a change has been successfully completed, which will remain in version control as a history of changes.

OpenSpec Specs

When the agent has implemented a change and before it is archived, the change's delta specs are "synced" to the application's root openspec/specs/ directory. This directory forms the full specification of your application so far.

This is important, because it serves as the single source of truth for your application's behavior, and will be used by future agents to understand the application when it makes new proposals or other changes. That way, new changes won't accidentally break existing features, unless that change's delta specs explicitly state that they should.

The OpenSpec Lifecycle

In order to manage the changes and specs, you direct the agent using four core slash commands in your agent chat.

  1. /opsx:propose [name] [prompt] The agent analyzes your prompt and generates all four change artifacts in a openspec/changes/[name]/ directory.
  2. /opsx:apply [name] The agent executes the generated task checklist (tasks.md), modifying or creating code files.
  3. /opsx:sync [name] The agent merges your change-level delta specifications into the main specs directory.
  4. /opsx:archive [name] The agent finalizes the change, moving the change folder into the archive registry.

The Explore Command

There is a fifth command, /opsx:explore, which allows you to brainstorm, ideate, and experiment with concepts before committing to a formal proposal. You don't need to use it, but the benefit over just normally conversing with the agent is that the explore command is strictly read-only and will never make any changes to your code or specs.

Arguments Optional

Note that the arguments for these commands are always optional. If you don't provide them, the agent will either make assumptions or ask you for more information.

However, the more information you provide, the better the change will match your expectations on the first attempt and the less you will need to iterate on the proposal.

Expanded Workflow

Note that there is an expanded workflow that gives you more granular control over the proposal process, allowing you to review and edit each planning artifact before generating the next.

This guide will assume you use the simplified workflow above, but if you're already familiar with that, you're welcome to switch to the expanded workflow by running openspec config profile expanded. Doing so would replace the /opsx:propose command with the /opsx:new and /opsx:continue commands.

What are Agent Guardrails?

To steer AI behavior effectively, modern harnesses use three distinct types of instructions. Recognizing their scope helps you write the right guardrails in the right places:

  • Profile: Universal project guidelines loaded automatically on every turn. Best for stack-wide architectural choices, styling paradigms, and core patterns.
  • Rules: Contextual guidelines loaded dynamically based on file paths, extensions, or model intent. Best for localized patterns, validation schemas, or component templates.
  • Skills: Executable command definitions or automated actions that extend the agent's capabilities. Best for automating terminal checks, build processes, or custom workflows.

Commands / Workflows

Some harnesses also support Commands AKA Workflows. While the profile, rules and skills are used by the agent, commands / workflows are like scripts (but defined in natural language) that the developer explicitly triggers inside the agent chat. The /opsx:propose command is an example of that.

We won't focus on building our own in this guide, but there's an opportunity to explore them in one of the afternoon tracks.

Harness Reference Sheet

Use the table below to identify where to place your guardrails depending on your AI harness:

HarnessProfileRulesSkills
Claude CodeCLAUDE.md.claude/rules/*.md.claude/skills/*/SKILL.md
AntigravityAGENT.md.agent/rules/*.md.agent/skills/*/SKILL.md
Cursor.cursorrules.cursor/rules/*.md.cursor/skills/*/SKILL.md
CodexAGENTS.mdAGENTS.md (nested).codex/skills/*/SKILL.md

What is HyperBytes?

HyperBytes is a hypothetical application that could be used to streamline our biweekly developer meetings. For example, it could include features such as:

  • Maintaining a backlog list of active discussion topics (e.g., tech presentations, proposal reviews, or tooling demos).
  • Upvoting topics to prioritize what to discuss first.
  • Commenting on topics to share feedback.
  • Generating slide presentations for individual topics with AI.
  • A live presentation view that is synchronized across all participants.
  • Archiving presented topics to keep the backlog clean.

In the morning session, we're going to build the foundation of HyperBytes—the backlog list, addition form, and browser persistence. In the afternoon session, you can pick a specialized track to implement advanced features like real-time synchronization, slide generation, or automated visual reviews.

Guide

Now that we know what we're building, let's get started.

No Cheating!

There are two rules to follow during this workshop:

  1. Throughout this guide, don't edit any source code by hand. You are only allowed to develop features, fix bugs, or refactor code by directing the agent, using OpenSpec commands, and editing the proposal artifacts.
  2. Make sure to keep this guide out of the context of your agent. Doing so would give away upcoming steps, which will defeat the purpose.

Chapter 1: Proposing a Feature

We'll start by asking the AI to design the core topic backlog feature with zero guardrails to observe the agent's default implementation choices.

No Initial Guardrails?

We intentionally do not provide any guardrails for learning purposes at this stage. However, new projects you start in the future will likely already come with some guardrails out of the box. Note that OpenSpec does not require this, but other SDD frameworks, such as SpecKit, do.

Step 1.1: Request the Proposal

Open your AI harness chat (Claude Code, Codex, Antigravity, or Cursor) and run the proposal command.

The application you are building is a local topic-backlog manager called "HyperBytes". For this first change, the application must display a list of discussion topics, each with a title and description, and provide a way to add and delete topics. Because this is a client-side app, all topics must persist locally in the browser so the data is preserved on reload.

Write a prompt in your own words describing this feature's requirements. Avoid copy-pasting the exact description above; instead, think about how to clearly communicate these functional requirements so the AI can design the solution.

TIP

A few sentences should do for now. The agent doesn't have a lot of information on your project yet, so it will make some assumptions. That's intentional as it's a good learning opportunity to refine the guardrails and the proposal, which we will do in upcoming chapters.

So don't worry about it too much for now, but know that in the future, the more information you provide here, the more aligned the proposal will be with your expectations on the first try.

Run /opsx:propose topic-backlog [prompt] with your prompt. The agent will automatically initialize the change directory and write all change artifacts (proposal.md, design.md, tasks.md, and specs/) under openspec/changes/topic-backlog/.

Step 1.2: Evaluate the Proposal

Since this is the very first proposal and the project doesn't include any guidelines for the AI at this point, it will probably be far from perfect.

Before letting the agent write any code, open the generated change directory under openspec/changes/topic-backlog/ and review the AI's proposed design across all four generated artifacts (proposal.md, specs/, design.md, and tasks.md).

TIP

Note that if you would rather take this process one artifact at a time, that "expanded workflow" I mentioned earlier is for you! But this feature is pretty small so you'll be fine reviewing them all at once.

Scan through the artifacts and note what you would change before letting the agent write any code. Below are some suggestions for things to look out for:

  • Completeness: Did the agent correctly interpret all of your requirements? If the specifications or task checklist are missing critical pieces (like storage persistence), your prompt was likely underspecified. Note what is missing.
  • Stack: Did the agent propose using third-party state managers (like Redux) or utility styling frameworks (like Tailwind)? Does it have a plan on how to handle form state?
  • Architecture: Does it plan to dump the entire implementation inside a single file (like App.tsx) or did it plan to split components logically?
  • Experience: Did the agent propose a user experience that aligns with your expectations? Did it take responsive design into account? Does it use appropriate UI patterns and follow accessibility guidelines?

Chapter 2: Refining the Proposal

In this phase, we'll align the agent's proposal with our preferred stack and fix any omissions or issues identified during step 1.2.

TIP

Although OpenSpec absolutely allows you to manually edit the change artifacts, or asking the agent to update them, doing so will only affect specs directly related to this change. For decisions that apply more generally to your project, you'll want to use guardrails. This is the topic of the next step.

Step 2.1: Write Basic Guardrails

To prevent the agent from deviating from our preferred stack and patterns, now and in the future, we'll establish your first set of guardrails.

Profile or Rules

Most of these preferences apply universally across the codebase, so you could put them in the Profile, but it's a bit more efficient to define them as Rules, so that if you have a conversation that doesn't require information about the stack, for example, it doesn't bloat the context. The profile is best suited for general agent behavior such as "always answer concisely".

Rule Inclusion

If you're using rules, note that some harnesses allow you to specify whether the rule should always be included or only when the agent decides that the rule is relevant based on a short description. The latter allows you to save tons of tokens, so it's often a good option to use.

So, create some files depending on your harness now and write some guardrails in your own words, inspired by the below suggestions:

  • Require the agent to use either React Context or Zustand for shared application state, whichever you like better.
  • Require the agent to use CSS Modules (*.module.css) for layout and component styling. Explicitly forbid inline styles and utility CSS frameworks such as Tailwind.
  • Require the use of React Hook Forms for form state and Zod for schema validation.
  • Require that each React component is placed in a separate file in its own directory. Or, if you prefer a feature-driven architecture, you can require that all related components are grouped.

TIP

When writing guardrails, try to be specific, but also try to be concise. Especially in the global profile, which is injected into the context on every turn, regardless of what you're discussing. Every letter in this file directly translates to additional cost. If you feel you're adding information that doesn't need to be in every turn, consider using a rule or skill instead.

Step 2.2: Update the Artifacts

Because OpenSpec is enabler-driven rather than strictly phase-locked, there is no single CLI command for regenerating artifacts. Instead, you refine the change plan to incorporate your new guardrails and correct any missing requirements using one of three options:

  1. Ask the Agent to Update the Artifacts (Recommended): Instruct the agent in the chat to update its change artifacts to conform to your new rules or requirements. The agent will read the modified rules file and update the design.md, specs/, and tasks.md in-place.
  2. Manually Edit the Artifacts: Since OpenSpec is built around fluid human-agent collaboration, you can open any of the files (e.g., design.md, proposal.md, or delta specs in specs/) and manually edit or add the details you need. In the next steps, the agent will read your edits as the updated source of truth.
  3. Delete and Start Fresh: Delete the generated design.md, tasks.md, and specs/ files in the change folder, and re-run /opsx:propose topic-backlog with a clearer prompt. The agent will rebuild the entire change plan from scratch. This is a bit rigorous, but sometimes it's easier.

Once updated, review all artifacts (proposal.md, specs/, design.md, and tasks.md) to ensure the entire plan conforms to your new rules.

Keep Going

Feel free to iterate as many times as you need until you are happy with the artifacts. If you like, you can have a conversation about the change with the agent and then ask the agent to update the artifacts accordingly.

Grill Me

A highly effective way to challenge the artifacts and your own thinking is to use the /grill-me skill. That skill is automatically included with Antigravity, but you can also install it using pnpm dlx skills add mattpocock/skills.

The Skills Package

The skills NPM package mentioned above is a great community package for installing skills from various sources. I highly recommend checking it out! You can chose whether you want to install a skill in the project, or globally in your user directory.

The Find Skills Skill

I know I'm going on about this package, but I just want to mention that it contains a find-skills skill, which gives your agent the power to recommend skills to you. Whenever you install a skill, it will ask if you want to also install the find-skills skill, and I highly recommend installing that globally.

Chapter 3: Implementing the Change

Now, let the agent implement the approved proposal.

Step 3.1: Apply the Change

Run /opsx:apply in the chat. The agent will read the updated checklist, create the context, build the components, and write the styles. As it writes the code, it will check off tasks in the tasks.md file one by one.

It's possible that it encounters an open question it can't resolve by itself. In that case, it will ask you for clarification in the chat. Respond to the agent's question and let it continue where it left off.

Step 3.2: Verify and Test the Functionality

Once /opsx:apply completes, run the app locally (with pnpm run dev) and test the functionality in your browser. Verify if the topic-backlog features work as expected.

It's likely that the agent included some entries in the tasks.md artifact that require manual validation by you. If that is the case, now is the time to do that. If they pass, you can manually mark them as complete in the artifact, or tell the agent to do so for you.

Take note of anything that isn't working as you want it to work, or perhaps of any features that it chose to implement that you didn't ask for and would like removed.

Step 3.3: Fix Functional Gaps

If you noticed any functional bugs or missing requirements during your manual testing:

  1. Resist the urge to write the fix yourself.
  2. In the chat, explain the issue to the agent and ask it to update the change artifacts accordingly. It will likely update the specs/, design.md and tasks.md files.
  3. Run /opsx:apply in the chat again. The agent will read the updated/unchecked tasks and implement the fix.

Repeat this loop until your backlog functionality is completely correct.

No Result?

If the /opsx:apply command results in the agent saying that the change is already complete and nothing needs to happen, it's likely because the agent did not update the tasks.md file when you requested changes to the artifacts. Just let it know about that and it will fix it for you.

Manual Control

OpenSpec is specifically designed to allow humans to edit those artifacts as well, so if you want more direct control, feel free to edit them yourself.

That said, your agent has official openspec skills for updating the change artifacts, so it should be pretty good at doing this! Just keep an eye out for whether the agent also validates the artifacts' formatting after it edits them, and whether it also updates the tasks.md file.

Chapter 4: Improving Code Quality

With the initial code generated, run local diagnostics to check if the implementation meets compilation and coding standards.

Step 4.1: Evaluate Quality

Now, evaluate implementation details:

  • Type Safety: Check the TypeScript files generated by the agent. Did it use any types, or did it use proper TypeScript types? Are types inferred correctly?
  • Linter Errors: Are there any linter errors in the generated code?
  • Code Style: Are you happy with the code style generated by the agent?

Check Command

The pnpm run check command will run the TypeScript compiler, the linter and prettier, which will help you evaluate the above three points.

  • Design Tokens: You may have noticed that the boilerplate contains some design tokens in the form of CSS variables defined in src/index.css. Check the CSS files generated by the agent. Did it use the CSS variables, or did it hardcode raw values?
  • Abstraction: Is all of the business logic abstracted away from the presentation logic? Are utilities written as pure functions in their own file?
  • Architecture: Are components either controlled or uncontrolled? Is the TopicContext accompanied by a Provider component that provides functions to read, create and delete topics?
  • Directory Structure: Does all of the code live where it should?
  • Template Use: Similarly, the project also contains a template file for new components at templates/react-component.tsx.tmpl. Did the agent use that template?

Step 4.2: Add Quality Guardrails

Update your guardrails to enforce code hygiene and quality. Because these checks are localized and execution-focused, they are best suited as Rules and/or Skills:

Below are just some suggestions. Try to tackle as much of the issues you noticed in Step 4.1 as possible:

  • Compiler & Linting Checks: A rule or skill requiring the agent to execute pnpm run check after making edits and resolve all compiler, linter and formatting errors.
  • CSS Variable Enforcement: A rule or skill targeted specifically at styling files (e.g. *.module.css) forbidding the agent from hardcoding colors or sizes, requiring it to reference CSS custom variables from index.css.
  • Component Skeletons: A rule or skill targeted at component creation (e.g. *.tsx) requiring the agent to inspect the /templates/ directory and match the structure of standard skeletons.
  • Documentation MCP: To prevent the agent from hallucinating or writing outdated code when integrating third-party packages, you can register the open-source Context7 MCP server. It connects to your agent and fetches live, version-specific package documentation from GitHub at query time.

TIP

When writing rules and skills, be critical of token use; be concise and specific, and make sure that each rule entry only touches one topic, so that the AI only needs to add tokens to the context that are actually relevant.

Step 4.3: Refactor the Implementation

Prompt the agent in the chat to audit its previous work. It should do so using the new rules.

Watch the agent clean up the code in a closed loop. Once the terminal checks compile cleanly, run /opsx:sync in the chat to merge the spec deltas into the main specifications, and then run /opsx:archive to seal and archive the change. Finally, commit your work to Git to establish your morning baseline.

Chapter 5: The Clean Run

To experience the speed of a well-guarded agent, we'll build a second feature with all rules active from the start.

Step 5.1: Propose the Filter Feature

In your harness chat, request a new proposal (e.g., search-filter) and describe the filtering requirements in your own words.

  • Topics should have a category tag field (or an array of them if you like).
  • The list view should allow filtering by title, description and category.

TIP

The Fuse.js library is a powerful, lightweight fuzzy-search library very suitable for this feature. If you want to force the agent to use it, you could mention it in your prompt or add it to the global profile. Or you can just see what the agent comes up with.

Step 5.2: Apply, Sync, and Archive

  1. Open the generated change directory. Review all regenerated artifacts (proposal.md, design.md, tasks.md, and specs/) and notice if the agent automatically plans to use the established stack and quality baseline.
  2. Run /opsx:apply to implement. Observe how the agent writes compliant, clean code on the first try.
  3. Run /opsx:sync to merge the spec deltas into the main specifications.
  4. Run /opsx:archive to seal the change, and commit the clean feature.

Next Steps

Congratulations! You have completed the morning session. Please commit your changes to create a checkpoint, so that you can easily roll back to this point later, which will be useful for the afternoon session.

If you're done early, feel free to experiment with adding an additional feature of your choice, or start with the afternoon session, in which you'll choose one of several predefined specializations.

Released under the MIT License.