正在学习

Step 3: Add structure and evaluation directive

14.3 Backend and API Prompts

Backend and API development is one of the strongest applications of Claude Code. Unlike traditional code generators that focus on boilerplate, Claude understands intent, logic flow, and architectural design. It can generate full backend modules, RESTful endpoints, and middleware pipelines while keeping your business logic clean and maintainable.

This section focuses on how to write effective backend prompts — prompts that produce working API servers, handle data validation, integrate databases, and manage error handling. Whether you’re working with FastAPI, Express.js, Flask, or Django, the goal is to show how Claude can assist in building production-grade backend systems through well-structured, context-rich requests.

Concept Development

Backend prompts differ from frontend prompts in one key way: they require precision in structure and functionality rather than aesthetics. Claude performs best when you provide:

  • The framework and programming language (e.g., “Python + FastAPI”).
  • The purpose of the API (e.g., “user authentication” or “task management”).
  • The requirements such as authentication, validation, or database connection.
  • The format of the expected output — a single module, multiple routes, or an entire service.
  • The environment constraints— whether it should use async functions, follow REST principles, or integrate with CI/CD tools.

By defining these clearly, you guide Claude to produce structured, testable, and deployable backend systems rather than generic snippets.

Hands-On Example 1: FastAPI CRUD Application

Prompt:

You are a senior Python backend engineer.

Build a FastAPI application for managing tasks with endpoints to:

  • Create, read, update, and delete tasks

  • Validate request bodies using Pydantic

  • Include exception handling for missing tasks

Return the complete runnable Python file.

Claude Output (Example):

from fastapi import FastAPI, HTTPException

from pydantic import BaseModel

from typing import List

app = FastAPI()

class Task(BaseModel):

    id: int

    title: str

    completed: bool = False

tasks: List[Task] = []

@app.post("/tasks", response_model=Task)

def create_task(task: Task):

    tasks.append(task)

    return task

@app.get("/tasks", response_model=List[Task])

def get_tasks():

    return tasks

@app.get("/tasks/{task_id}", response_model=Task)

def get_task(task_id: int):

    for task in tasks:

        if task.id == task_id:

            return task

    raise HTTPException(status_code=404, detail="Task not found")

@app.put("/tasks/{task_id}", response_model=Task)

def update_task(task_id: int, updated_task: Task):

    for i, task in enumerate(tasks):

        if task.id == task_id:

            tasks[i] = updated_task

            return updated_task

    raise HTTPException(status_code=404, detail="Task not found")

@app.delete("/tasks/{task_id}")

def delete_task(task_id: int):

    for i, task in enumerate(tasks):

        if task.id == task_id:

            tasks.pop(i)

            return {"detail": "Task deleted"}

    raise HTTPException(status_code=404, detail="Task not found")

Why It Works: The prompt specifies the framework, data validation, and error handling, allowing Claude to produce a complete, functional FastAPI app — no incomplete placeholders, no missing imports. The result runs directly with uvicorn main:app --reload.

Hands-On Example 2: Node.js Express API with Middleware

Prompt:

Create a Node.js Express API that manages user authentication.

Include:

  • Endpoints for register and login

  • Password hashing using bcrypt

  • Token generation using JWT

  • Middleware to protect private routes

Return one complete file ready to run.

Claude Output (Example):

import express from "express";

import bcrypt from "bcryptjs";

import jwt from "jsonwebtoken";

const app = express();

app.use(express.json());

const users = [];

const SECRET = "mysecretkey";

app.post("/register", async (req, res) => {

    const { username, password } = req.body;

    const hashed = await bcrypt.hash(password, 10);

    users.push({ username, password: hashed });

    res.status(201).json({ message: "User registered successfully" });

});

app.post("/login", async (req, res) => {

    const { username, password } = req.body;

    const user = users.find((u) => u.username === username);

    if (!user) return res.status(404).json({ message: "User not found" });

    const valid = await bcrypt.compare(password, user.password);

    if (!valid) return res.status(401).json({ message: "Invalid credentials" });

    const token = jwt.sign({ username }, SECRET, { expiresIn: "1h" });

    res.json({ token });

});

function auth(req, res, next) {

    const authHeader = req.headers.authorization;

    if (!authHeader) return res.status(401).json({ message: "Missing token" });

    try {

        const decoded = jwt.verify(authHeader.split(" ")[1], SECRET);

        req.user = decoded;

        next();

    } catch {

        res.status(401).json({ message: "Invalid token" });

    }

}

app.get("/profile", auth, (req, res) => {

    res.json({ message: `Welcome ${req.user.username}!` });

});

app.listen(4000, () => console.log("Server running on port 4000"));

Key Takeaways:

  • The prompt defines security mechanisms (JWT, bcrypt) and specific routes, ensuring completeness.
  • Claude correctly includes middleware and authentication logic, which is often missing in generic AI code.
  • The output runs without modification using node app.js (after installing dependencies).

Hands-On Example 3: Flask API with Database Integration

Prompt:

Build a Flask REST API for a book catalog.

Include:

  • SQLite database integration

  • SQLAlchemy ORM models

  • CRUD routes for books

  • Error handling for invalid operations

Return a complete runnable Python script.

Claude Output (Example):

from flask import Flask, request, jsonify

from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///books.db"

db = SQLAlchemy(app)

class Book(db.Model):

    id = db.Column(db.Integer, primary_key=True)

    title = db.Column(db.String(100), nullable=False)

    author = db.Column(db.String(100), nullable=False)

@app.before_first_request

def create_tables():

    db.create_all()

@app.route("/books", methods=["POST"])

def add_book():

    data = request.get_json()

    book = Book(title=data["title"], author=data["author"])

    db.session.add(book)

    db.session.commit()
{
"code": "return jsonify({\"message\": \"Book added successfully\"}), 201\n\n@app.route(\"/books\", methods=[\"GET\"])\ndef get_books():\n    books = Book.query.all()\n    return jsonify([{\"id\": b.id, \"title\": b.title, \"author\": b.author} for b in books])\n\n@app.route(\"/books/<int:book_id>\", methods=[\"GET\"])\ndef get_book(book_id):\n    book = Book.query.get(book_id)\n    if not book:\n        return jsonify({\"error\": \"Book not found\"}), 404\n    return jsonify({\"id\": book.id, \"title\": book.title, \"author\": book.author})\n\n@app.route(\"/books/<int:book_id>\", methods=[\"DELETE\"])\ndef delete_book(book_id):\n    book = Book.query.get(book_id)\n    if not book:\n        return jsonify({\"error\": \"Book not found\"}), 404\n    db.session.delete(book)\n    db.session.commit()\n    return jsonify({\"message\": \"Book deleted\"})\n\nif __name__ == \"__main__\":\n    app.run(debug=True)\n\n## 14.4 Testing and Debugging Prompts\nTesting and debugging are where Claude Code transitions from being a coding assistant to acting as a software quality partner. Well-written prompts can help Claude not only generate test cases but also diagnose logic errors, interpret stack traces, and even explain how to fix bugs. This section focuses on writing structured, reproducible testing and debugging prompts that yield high-quality, verifiable results.\n\nClaude’s advantage lies in its ability to reason contextually — to understand what a function should do, detect why it fails, and produce both tests and fixes in a single workflow. With the right prompt structure, you can treat Claude as a flexible test engineer that complements your own intuition and saves hours of manual inspection.\n\n### Concept Development\nWhen prompting Claude for testing and debugging, clarity and containment are critical. Unlike human testers, Claude does not infer unstated requirements well — you must specify scope, framework, and expected behavior explicitly. Key prompt elements that consistently yield strong results include:\n\n- Framework specification– e.g., “Use pytest,” “Use Jest,” or “Use unittest.”\n- Coverage scope– Define which functions, modules, or edge cases to test.\n- Expected format– Ask for runnable test files, not snippets.\n- Error handling– Provide sample stack traces for Claude to analyze.\n- Verification intent– Instruct Claude to confirm that the fix passes all tests.\n\nA well-structured debugging prompt doesn’t just request a fix; it explains the observed behavior and invites Claude to reason through it step-by-step.\n\n### Hands-On Example 1: Writing Unit Tests with Pytest\n**Prompt**:\nYou are a Python QA engineer.\nWrite pytest test cases for the following function.\nEnsure coverage for valid input, invalid input, and edge cases.\nReturn a complete runnable test file.\n\n```python\ndef divide(a, b):\n    return a / b\n```\n\n**Claude Output (Example)**:\n```python\nimport pytest\nfrom main import divide\n\ndef test_divide_valid():\n    assert divide(10, 2) == 5\n    assert divide(-6, 3) == -2\n\ndef test_divide_zero_division():\n    with pytest.raises(ZeroDivisionError):\n        divide(5, 0)\n\ndef test_divide_floats():\n    assert pytest.approx(divide(5.0, 2.0), 0.001) == 2.5\n\ndef test_divide_large_numbers():\n    assert divide(1_000_000, 10) == 100_000\n```\n\n**Explanation**: Claude created a clean, structured test file with edge coverage — including floating-point precision and error handling. It automatically inferred boundary conditions without being told exactly what to test, thanks to a well-framed prompt.\n\n### Hands-On Example 2: Debugging with Error Trace Analysis\n**Prompt**:\nYou are a debugging assistant.\nAnalyze the following Python traceback and identify the root cause.\nThen, rewrite the buggy code correctly with an explanation.\n\n```\nTraceback (most recent call last):\n  File \"app.py\", line 10, in <module>\n    result = calculate_area(5)\nTypeError: calculate_area() missing 1 required positional argument: 'height'\n\n```python\ndef calculate_area(width, height=2):\n    return width * height\n```\n\n**Claude Output (Example)**:\n```python\n# Fixed Code\ndef calculate_area(width, height=2):\n    return width * height\n\n# Correct Usage\nresult = calculate_area(5, 4)\nprint(result) # Output: 20\n```\n\n**Explanation**: Claude correctly identifies the issue — the function call is missing a required positional argument. It not only provides the corrected code but also explains the fix in context, turning debugging into a learning process rather than a guessing game.\n\n### Hands-On Example 3: JavaScript Jest Test Automation\n**Prompt:**\nWrite Jest test cases for the following Express.js route.\nCover success, failure, and validation scenarios.\n\n```javascript\napp.post(\"/users\", (req, res) => {\n    const { name, email } = req.body;\n    if (!name || !email) return res.status(400).json({ message: \"Invalid input\" });\n    res.status(201).json({ message: \"User created\" });\n});\n```\n\n**Claude Output (Example):**\n```javascript\nimport request from \"supertest\";\nimport express from \"express\";\n\nconst app = express();\napp.use(express.json());\n\napp.post(\"/users\", (req, res) => {\n    const { name, email } = req.body;\n    if (!name || !email) return res.status(400).json({ message: \"Invalid input\" });\n```"
}
res.status(201).json({ message: "User created" });

});

describe("POST /users", () => {

it("should create a user successfully", async () => {

const res = await request(app)

.post("/users")

.send({ name: "Alice", email: "alice@example.com" });

expect(res.statusCode).toBe(201);

expect(res.body.message).toBe("User created");

});

it("should return 400 for invalid input", async () => {

const res = await request(app).post("/users").send({});

expect(res.statusCode).toBe(400);

});

});

Why It Works: The prompt defines three expectations — framework, test coverage, and validation behavior. Claude responds with a working test suite that uses Supertest, handles both valid and invalid inputs, and runs immediately in Node.js.

Hands-On Example 4: Debugging Logic Errors in a Loop

Prompt:

Analyze this Python code that produces incorrect results.

Explain the logical bug and provide the corrected version.

def calculate_sum(numbers):

total = 0

for num in numbers:

total = num # bug here

return total

print(calculate_sum([1, 2, 3]))

Claude Output (Example):

练习题

When writing backend prompts for Claude Code, which of the following is NOT a key requirement?

A. The framework and programming language (e.g., 'Python + FastAPI')
B. The purpose of the API (e.g., 'user authentication' or 'task management')
C. The expected output format (e.g., single module, multiple routes, or entire service)
D. The color scheme for the frontend interface

In the FastAPI CRUD application prompt example, what was the main goal of the prompt?

A. To create a frontend interface for task management
B. To build a FastAPI application for managing tasks with specific endpoints and features
C. To design a database schema for task management
D. To implement a user authentication system for the FastAPI application

Which of the following are characteristics of effective backend prompts for Claude Code? (Select all that apply)

A. They are vague and open-ended to allow for creativity
B. They specify the framework and programming language
C. They define the purpose of the API
D. They include requirements such as authentication or database connection
E. They describe the expected output format

What are the benefits of including environment constraints in backend prompts for Claude Code? (Select all that apply)

A. It ensures the generated code follows REST principles
B. It helps Claude produce code that integrates with CI/CD tools
C. It makes the prompts more aesthetically pleasing
D. It guides Claude to use async functions when appropriate
E. It reduces the need for data validation in the generated code

Backend prompts for Claude Code should focus on aesthetics rather than structure and functionality.

The FastAPI CRUD application prompt example was successful because it specified data validation and error handling requirements.

In backend prompts, providing the ___ and programming language (e.g., 'Python + FastAPI') helps Claude generate code that aligns with your technology stack.

The ___ of the API (e.g., 'user authentication' or 'task management') is an important aspect to define in backend prompts for Claude Code.

Explain why it is important to specify the expected output format in backend prompts for Claude Code.

What are the key takeaways from the Node.js Express API prompt example for user authentication?

Which of the following is a benefit of using a reusable prompt library in Claude Code development?

A. It reduces the need for version control
B. It ensures every developer has access to proven, high-performing prompts
C. It eliminates the need for troubleshooting
D. It makes prompts more aesthetically pleasing

What are the three principles of iterative tuning in Claude Code prompt development? (Select all that apply)

A. Observation: Analyze the model's output carefully
B. Modification: Adjust the language of the prompt
C. Validation: Re-test with the same inputs and compare outputs
D. Automation: Integrate the prompt into the codebase without testing
E. Aesthetics: Focus on making the prompt visually appealing

When writing a backend prompt for a Node.js Express API with user authentication, which of the following is NOT a key requirement to specify in the prompt for Claude to generate a complete and functional application?

A. The programming language (Node.js) and framework (Express)
B. The purpose of the API (user authentication)
C. The expected output format (e.g., JSON)
D. The color scheme for the authentication pages

Which of the following are essential components to include in a FastAPI CRUD application prompt to ensure Claude generates a complete and functional application? (Select all that apply)

A. The framework and programming language (e.g., Python + FastAPI)
B. The purpose of the API (e.g., task management)
C. Requirements for data validation (e.g., using Pydantic)
D. The expected output format (e.g., a single module)
E. The font size for the API documentation

In a backend prompt for a Flask API with database integration, specifying the database type (e.g., SQLite) and the ORM (e.g., SQLAlchemy) is necessary for Claude to generate a complete and functional application.

Explain why including error handling requirements in a backend prompt is important for generating a functional API.

登录后解锁笔记、知识点解析、AI 问答

立即登录