Harness + SDD + Multi-Agent: A Production-Proven Full-Stack AI Development Workflow
1. Core Concept: Harness Thinking — Let AI Imitate, Not Create from Scratch
The Most Common Pitfall in Full-Stack AI Development
In full-stack SDD development, the most common and fatal mistake is letting AI write code from scratch. AI models have "general knowledge" — give them a requirement description, and they can indeed generate runnable code. But the problem is that this code is often "alien code": inconsistent style (naming conventions, directory structure, layering differ from existing project code), low reusability (doesn't leverage existing project components, utility functions, request wrappers), low adoption rate (during Code Review, backend developers see "foreign-style" code and generate lots of revision comments). The result: AI generates code, but review costs and rework costs are even higher.
The Essence of Harness Thinking: Give AI a "Model to Imitate"
The essence of Harness (constraint) thinking is: give AI an existing implementation as a reference, and have it replicate it accordingly, rather than creating from scratch. It's like telling a new engineer "follow the style of this module and write something similar," rather than "be creative" — the former tends to produce code that meets team standards faster.
Reflecting Harness in Prompts
Not recommended (creating from scratch):
Please implement a CRUD interface for closing remarks management
Recommended (Harness constraint):
Please refer to the existing "Scenario Greeting" feature (backend interface /api/v1/feature/list, frontend entry FeatureTable/index.tsx:53-58) to implement the "Closing Remarks" feature. Keep data structures, layering, and naming conventions consistent. New scenario code: categoryCode = "SCENARIO_CLOSING"
The difference between the two isn't about how "smart" the AI is, but how many constraints and context you give the AI. The more precise the constraints, the higher the usability of the generated code.
2. Full-Stack Workspace Setup & Codebase Indexing
Why Set Up a Multi-Repo Workspace?
Frontend and backend code are usually in two separate repositories. If opened separately, when AI generates backend interfaces, it can't see frontend call patterns; when generating frontend code, it can't see backend return structures. Interface field mismatches are common. Placing frontend and backend code in the same workspace has three core values: Codebase Indexing: Cursor performs vector embedding on all code in the workspace, building a semantic index. AI can understand code relationships across repositories, greatly improving generation quality. Complete Context: AI can see both frontend and backend code simultaneously, so interface fields and naming styles naturally align. Centralized SDD Document Management: Frontend and backend SDD documents are in the same workspace, facilitating interface contract alignment.
The Value of Codebase Indexing
Cursor's Codebase Indexing performs vector embedding on code in the workspace, building a semantic index. This means: when you ask AI "how is the scenario greeting implemented," it doesn't need you to manually specify files; it can automatically find related Controllers, Services, and frontend components through semantic search. When you tell AI "write the closing remarks following the greeting," it retrieves the complete frontend-backend implementation chain of the greeting, not just a single file.
Placing frontend and backend in the same workspace means Codebase Indexing covers both sides. When AI generates backend interfaces, it can reference frontend call patterns; when generating frontend code, it can reference backend return structures.
Tips: After Cursor opens a workspace, the initial indexing may take a few minutes. You can check the indexing progress in Cursor settings. Ensure indexing is complete before asking AI to generate code for significantly better results.
Cursor vs Claude Code: Which to Choose?
In full-stack AI development scenarios, both tools have their strengths. The table below shows a practical comparison:
Full-Stack Workspace Setup & SDD Initialization — Internal Full-Stack Development Plugin
Using the above requirement as an example, the workspace structure is as follows. The .claude and .cursor directories have already been initialized with SDD capabilities.
3. SDD-Driven Full-Stack Code Generation Process
What Makes Full-Stack SDD Special
Unlike pure frontend/pure backend SDD, full-stack SDD requires: generating two SDD documents (one for frontend, one for backend); interface contract alignment, where frontend SDD interface calls must strictly correspond to backend SDD interface definitions; consistent field mapping, where frontend VO field names must match backend JSON return field names one-to-one.
Related Concepts and Terminology
Prompt Writing Paradigm
Below is a proven full-stack SDD generation prompt template:
This is a frontend-backend full-stack development workspace. You need to design a technical interface solution and develop both frontend and backend projects. First, you need to `cd` to the corresponding frontend/backend application directories and create SDD files. So you need to generate two SDD documents. After that, I will start two agents to implement them respectively. Before generating, if you need to confirm certain details, you should confirm them first before generating the SDD documents. Frontend application: service-frontend/sdd-propose feature/your-feature-name Frontend modification entry reference: @FeatureTable/index.tsx:53-58 @columns/index.tsx Backend application: service-backend/sdd-propose feature/your-feature-name Backend modification entry reference interface: /api/v1/feature/list Requirements content: (Attach requirement documents or descriptions, and provide a checklist of frontend and backend requirements)
Key Elements Explained:
Example Frontend and Backend Requirements Checklist Division
Frontend Requirements Function Points
Mainly involves adding a new tab to the admin management page, including search, display, configuration add, delete, etc. Using an internal SDD document tool (as shown below) to extract requirements from PRD descriptions and document images.
Internal SDD Document Tool
Add a "Closing Remarks" tab on the left navigation. Add a Closing Remarks list page on the right. Fields include: Closing remark content, Closing remark description, Priority, Updated by, Update time, Action column.
Add/Edit popup fields: Closing remark description, Effective date, Effective time period, Effective time period, Closing remark script (types and rules are not listed here one by one).
Drag-and-drop sorting: Click the "Sort" button to enter sorting mode, drag to adjust order, then click "Save" to apply.
Backend Function Points (Including Interface List)
The backend functionality is designed by AI independently based on frontend requirements, including data tables and interfaces. Below are key design questions AI needs to clarify before generating SDD (these should be listed in the prompt, asking AI to answer first before generating).
Interface List: List interface (supports pagination, display data embedded directly in list response, no separate display interface needed), Add interface, Edit interface (reuses add logic, updates based on id), Delete interface (logical delete, modifies delete status field), Sort interface (batch update, needs efficient implementation).
Field Design: Closing remark script content (array type), Closing remark description (text), Priority/Sequence number (small integer), Updated by (string), Update time (timestamp).
Design Questions AI Must Answer Clearly in SDD:
- Primary key design: How to design the primary key field? The frontend needs to pass this field when initiating edit/delete.
- Priority auto-increment logic: Priority should auto-increment based on the current number of data records, no need for frontend to pass, handled automatically by backend.
- How to efficiently update sorting: How to design the interface for batch sorting to avoid N single updates?
- How to create tables for nested objects: Refer to the existing "Scenario Greeting" interface, where input parameters contain nested sub-objects (see reference structure below). Should such sub-objects be split into multiple tables, or serialized as JSON fields in a single table?
- Meaning of
isNextDayfield: What exactly is the logic for "next day"? How does the "next day" checkbox state in the frontend time period selector map to this field? - List display design: The list interface needs to return complete display data (for populating edit popup), no need for a separate detail interface.
Why Include This Checklist in the Prompt?
This checklist does two important things: On the frontend side, it gives AI complete UI details, letting AI know component states, field constraints, interaction logic, preventing it from doing "minimal implementation." On the backend side, it exposes vague design questions upfront, letting AI answer these questions before writing SDD — this embodies Harness thinking: letting AI reference existing implementations (like "Greeting") to solve "Closing Remarks," rather than designing from scratch.
SDD Document Output
A complete full-stack SDD generation produces the following documents:
Frontend SDD:
proposal.md— Requirement proposal, describing what the frontend needs to do.spec.md— Technical specification, component design, interface calls, state management.tasks.md— Task breakdown, each task corresponds to an executable code change.
Backend SDD:
proposal.md— Requirement proposal, describing what the backend needs to do.spec.md— Technical specification, interface design, database design, layering architecture.design.md— Detailed design, class diagrams, field mappings, SQL.tasks.md— Task breakdown.
SDD Command Usage Instructions
Typical Workflow Examples
Getting Started Guide:
openspec-onboard(first time, only if unfamiliar, guides through complete steps);openspec-continue-change(prompts what to do next);openspec-ff-change(fast forward).
Scenario A: Initial Development
openspec-explore(research, brainstorm);openspec-propose "..."(generate design);openspec-apply-change(write code);openspec-verify-change(self-test, verify code matches SDD documents);openspec-archive-change(wrap up, archive).
Scenario B: Secondary Development, Modifying Existing Features
openspec-explore(locate old code/old spec);openspec-propose "Modify..."(generate change spec);openspec-apply-change(apply modifications);openspec-verify-change(verify regression);openspec-archive-change(archive).
Scenario C: Secondary Modification, Requirement Change
openspec-explore(research, brainstorm);openspec-propose "..."(generate design);openspec-apply-change(write code);- If issues found, use
openspec-exploreto modify the proposal; openspec-explore "Requirement change: xxx"(secondary brainstorm);openspec-propose "Modify proposal based on exploration results";openspec-apply-change(execute changes in the proposal);[Optional] openspec-verify-change(verify if there are unfinished tasks);openspec-archive-change(archive).
Scenario D: Quarterly Cleanup
openspec-bulk-archive-change --before 2023-12-31(batch archive).
Overall, the above is still relatively cumbersome. Keep it minimal: Think (openspec-propose), Do (openspec-apply-change), Archive (openspec-archive-change) is sufficient.
4. Multi-Agent Collaboration: Parallel Frontend and Backend Development
Why Multi-Agent is Needed
After SDD document generation, the code generation work for frontend and backend is independent — frontend generates components and pages based on frontend SDD, backend generates Controller/Service/Repository based on backend SDD. This is naturally suited for parallel execution.
Multi-Agent Collaboration in Cursor
Cursor supports multiple AI coding modes working in parallel, which is one of its core advantages. In full-stack development scenarios: Tab 1 handles frontend code generation, Tab 2 handles backend code generation, both agents run simultaneously without blocking each other.
Subagent Capability in Claude Code
Claude Code has a built-in Subagent mechanism, suitable for multi-task parallelism in command-line scenarios.
Subagent Modes
Claude Code provides two multi-agent collaboration modes. (Will test the difference between Team mode and regular Subagent in the next iteration.)
Subagent Configuration and Usage
Core configuration items for Subagent:
{
"description": "Frontend code generation expert",
"tools": ["Read", "Edit", "Write", "Bash", "Grep"],
"permissionMode": "bypass",
"model": "sonnet",
"skills": ["Frontend coding standards"]
}
Application in full-stack development scenarios:
Main Agent (the Claude Code you are chatting with)
├── Subagent 1: Read frontend SDD, generate frontend code
│ ├── model: sonnet
│ ├── tools: Read, Edit, Write, Bash
│ └── Task: Generate frontend components according to tasks.md
│
├── Subagent 2: Read backend SDD, generate backend code
│ ├── model: sonnet
│ ├── tools: Read, Edit, Write, Bash
│ └── Task: Generate backend interfaces according to tasks.md
│
└── Subagent 3: (Optional) Generate interface Mock data
├── model: haiku
└── Task: Generate Mock data based on backend SDD spec.md
Multi-Agent Practical Suggestions
5. Frontend-Backend Integration: Mock Data and Phased Verification
Three-Phase Verification Strategy
Direct integration is often the least efficient verification method. A three-phase separated verification is recommended:
Phase 1: Frontend Mock Verification
Frontend code + Mock data → Run page interactions locally, verify UI logic
Phase 2: Backend Independent Verification
Backend code → mvn clean compile → Build passes → Deploy to test environment
Phase 3: Frontend-Backend Integration
Frontend connects to test backend interface → End-to-end verification
The benefit: Issues on both sides can be discovered early and fixed separately; avoids exposing problems only during integration; saves significant debugging time.
Key Points for Writing Mock Data
Mock data quality directly determines the effectiveness of frontend self-testing. There are three key requirements: Field names and types must exactly match those defined in the backend SDD; Reference real return data from existing interfaces as templates, rather than constructing arbitrarily; Cover edge cases (empty list, single record, multiple records, field extremes like empty strings, very long strings, null values, etc.).
Backend Independent Build Verification
Backend code doesn't need to fully start the entire Java service locally; just compiling successfully can verify most code issues.
# Switch to Java 8 environment (adjust based on project's actual JDK version)
sdk use java 8
# Enter backend project directory
cd service-backend
# Compile verification (no need to start the entire service locally)
mvn clean compile
Compilation passing means: correct syntax, correct dependency relationships, type compatibility. It's the fastest verification method before deployment.
Frontend-Backend Integration Steps
Backend code is committed and deployed to the test environment; The frontend local development service uses proxy configuration to point API requests to the test backend address; Frontend requests carry a feature routing identifier to ensure requests are routed to the corresponding test environment (not someone else's); Verify interfaces one by one, focusing on field mapping, state handling, and error scenarios.
6. Beware of SDD Pitfalls: How Testing Intervenes in Full-Stack Development
SDD is Not a Requirements Document
This is the most overlooked issue in AI full-stack development. SDD describes "how to implement technically" , not "all business behaviors" . When AI mimics reference code to generate new code, it automatically replicates many implicit features — these features exist in the reference code, AI considers them "taken for granted," so they are not written into the SDD document, but are actually quietly implemented.
Examples of Implicit Features
Example 1: Variable/Form Clearing (Frontend)
// AI mimics the greeting popup to generate the closing remarks popup, automatically replicating the "clear form on close" logic
const handleClose = () => {
form.resetFields(); // ← Implicit feature: Clear form fields on close
setContentList([]); // ← Implicit feature: Clear content list state
setVisible(false);
};
Example 2: Data Format Conversion (Backend)
// AI mimics existing interfaces, automatically adding business logic judgment
if (extendInfo.getIsPermanent()) {
extendInfo.setEffectiveDate(null); // ← Implicit: Automatically clear start date when permanent
extendInfo.setExpirationDate(null); // ← Implicit: Automatically clear end date when permanent
}
Example 3: Default Value Completion (Backend)
// AI automatically implements "priority auto-increment" logic, not mentioned in SDD document
if (Objects.isNull(req.getSequence())) {
req.setSequence(getMaxSequence() + 1); // ← Implicit: Priority auto-increments on add
}
These implicit features might be exactly what's needed, or they might completely not meet current requirements. The problem is you don't know they exist.
Testing Intervention Suggestions
Practical advice for QA colleagues: Treat SDD documents as a starting point, not an endpoint. Focus on reviewing the code generated by AI, and ask yourself: "What implicit behaviors does the reference feature have? Are these behaviors appropriate for the new feature?"
7. Comprehensive Benefits and Summary
Practical Benefits
Through the "Harness + SDD + Multi-Agent" full-stack development methodology introduced in this article, the benefits verified in actual projects are: Adoption rate improved: Compared to traditional separated frontend-backend development, the workspace mode effectively brings project requirement context together, making it easier for AI to understand requirements, design, and code. Especially through Cursor's indexing capability, it further improves adoption rate and feature implementation completeness. Time reduced: In SDD mode, AI analyzes requirements and produces two sets of SDD documents, allowing frontend and backend development to proceed in parallel. Taking this requirement as an example, originally requiring 2+4 person-days for frontend and backend, under this mode, including environment setup, troubleshooting time, integration and self-testing time, it was compressed to 3 person-days, a 50%+ efficiency improvement. Debugging is not blocking: With a full-stack development perspective, known data structures can be mocked for frontend self-testing; backend functionality supports local breakpoint debugging through remote debugging; finally, both are verified together in the test environment, making it clear whether issues come from frontend or backend. AI full-stack learning cost drops sharply: Only entry-level frontend and backend knowledge is needed to get involved in simple full-stack requirement development; improving business domain requirement throughput.
Methodology Summary
The full-stack AI development methodology introduced in this article can be summarized in one diagram:
This article is compiled based on actual full-stack development project experience. All code examples have been anonymized, using generic naming instead of business-specific terms. Feel free to discuss and exchange ideas.
Previous Reviews
- General AI Agent-Driven Gateway Routing Security Audit Practice | Dewu Technology
- AI-Driven: Intelligent Practice from Operational Behavior to Automated Test Cases | Dewu Technology
- Landing Technology Sharing and Thoughts on Generative Recall at Dewu
- Stand at Attention: Engineering Practice of a Component Reuse Skill | Dewu Technology
- Financial Data Warehouse Claude AI Coding Application Practice | Dewu Technology
Author: Galen
Follow Dewu Technology, weekly technical updates
If you find the article helpful, feel free to comment, repost, and like~
Reproduction is strictly prohibited without permission from Dewu Technology, otherwise legal liability will be pursued.