正在学习
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?
In the FastAPI CRUD application prompt example, what was the main goal of the prompt?
Which of the following are characteristics of effective backend prompts for Claude Code? (Select all that apply)
What are the benefits of including environment constraints in backend prompts for Claude Code? (Select all that apply)
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?
What are the three principles of iterative tuning in Claude Code prompt development? (Select all that apply)
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?
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)
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 问答
立即登录