Best Practices for Legal Services Prompt Engineering with Claude: A Complex Prompt Template Approach

Separate raw legal data from instructions using input variables and enforce traceability through explicit citation formats to build reliable Claude prompts for legal research.

The anthropics/prompt-eng-interactive-tutorial repository provides a production-ready framework for legal services prompt engineering with Claude, demonstrating how structured templates reduce hallucination risks while maintaining flexibility for iterative refinement. The approach centers on a reusable complex-prompt architecture that isolates dynamic legal content from static system instructions, enabling lawyers to swap case materials without rewriting core prompts.

The Complex Prompt Architecture

The legal-service implementation in Anthropic 1P/09_Complex_Prompts_from_Scratch.ipynb establishes a three-tier structure that separates concerns between data, instructions, and formatting constraints. This modular design aligns with Claude's Messages API expectations while accommodating the variable nature of legal research workflows.

The template defines distinct input variables that inject raw legal documents separately from the prompt text. This separation allows practitioners to update case law or statutes without modifying the underlying prompt logic.


# First input variable – the legal document

LEGAL_RESEARCH = """
<search_results>
<search_result id=1>
... (legal excerpts) ...
</search_result>
<search_result id=2>
... (more excerpts) ...
</search_result>
</search_results>
"""

# Second input variable – the user's question

QUESTION = "Are there any laws about what to do with pets during a hurricane?"

By encapsulating the legal research within LEGAL_RESEARCH and the client query within QUESTION, the system maintains clean boundaries between factual inputs and instructional context.

Prompt Elements and Role Definition

The architecture mandates specific prompt elements that establish Claude's behavioral parameters. According to the source implementation, every Messages API call must begin with a user role header to ensure the model treats the legal query as a user request rather than system configuration. The template incorporates system instructions, conversational role definition, and example-based learning within a flexible ordering scheme that supports experimentation.

Citation and Formatting Requirements

Legal applications demand rigorous source attribution. The tutorial enforces strict citation protocols and output constraints that align with professional legal writing standards.

The prompt template requires Claude to place citations in brackets containing the search-index ID followed by a period (e.g., [1.]). This convention appears in 09_Complex_Prompts_from_Scratch.ipynb where the prompt explicitly states that citations must reference the corresponding <search_result id> from the injected research data. This bracket-ID format guarantees traceability, allowing attorneys to verify every factual claim against the underlying legal authority.

Output Structure Constraints

The notebook emphasizes output constraints that force Claude to produce concise, well-structured answers using bullet points or numbered lists. These formatting requirements prevent verbose responses and ensure compliance with legal document standards. The implementation notes that "we've changed around the ordering of a few elements to showcase that prompt structure can be flexible," enabling rapid A/B testing of different constraint placements without breaking the citation logic.

Implementation Workflow

Building on the template from 09_Complex_Prompts_from_Scratch.ipynb, the following workflow integrates legal research into Claude's Messages API:


# 1️⃣ Load legal research (could be from a vector store, file, etc.)

LEGAL_RESEARCH = """
<search_results>
<search_result id=1>
... (legal excerpts) ...
</search_result>
<search_result id=2>
... (more excerpts) ...
</search_result>
</search_results>
"""

# 2️⃣ Define the client's question

QUESTION = "Are there any laws about what to do with pets during a hurricane?"

# 3️⃣ Assemble the complex prompt (simplified)

prompt = f"""
You are a knowledgeable legal assistant. 
Use the provided legal research to answer the user's question. 
Cite each fact with the corresponding <search_result id> in brackets, e.g., [1.].

<legal_research>
{LEGAL_RESEARCH}
</legal_research>

Question: {QUESTION}
"""

# 4️⃣ Call Claude (pseudocode – replace with actual SDK call)

response = claude.messages([{"role": "user", "content": prompt}])

print(response.content)

This workflow ensures that raw legal texts remain modular while the prompt maintains consistent instructional framing across different cases.

Supporting Techniques from the Tutorial

While 09_Complex_Prompts_from_Scratch.ipynb provides the core template, complementary notebooks in the repository address specific legal AI challenges:

  • Hallucination Prevention: Anthropic 1P/08_Avoiding_Hallucinations.ipynb demonstrates grounding techniques that complement legal prompt design by restricting Claude to provided search results rather than latent knowledge.
  • Output Formatting: Anthropic 1P/05_Formatting_Output_and_Speaking_for_Claude.ipynb details conventions for legal document structures, ensuring AI-generated briefs and memos follow professional formatting standards.

Summary

  • Separate data from instructions using input variables like LEGAL_RESEARCH and QUESTION to enable rapid document swapping without prompt rewriting.
  • Enforce citation traceability through bracket-ID formats (e.g., [1.]) that map directly to search result indices.
  • Begin with user roles in the Messages API to align with Claude's conversational architecture and prevent instruction hierarchy confusion.
  • Modularize prompt sections (system instructions, examples, output format) to support iterative A/B testing of legal prompt variations.
  • Combine with grounding techniques from 08_Avoiding_Hallucinations.ipynb to minimize fabrication risks in legal analysis.

Frequently Asked Questions

Ground all responses in explicit external data by including the relevant statutes or cases in the LEGAL_RESEARCH input variable. According to 08_Avoiding_Hallucinations.ipynb, instructing Claude to cite only the provided search results using the bracket-ID format significantly reduces hallucination risks in legal research tasks.

Always initiate the Messages API call with a user role containing the assembled prompt. As implemented in 09_Complex_Prompts_from_Scratch.ipynb, starting with the user role ensures Claude interprets the legal query as a client request rather than system configuration, maintaining proper conversational flow.

Can I reorder prompt elements without breaking citation functionality?

Yes. The tutorial explicitly showcases flexibility by changing the ordering of non-dependent elements while preserving the citation bracket format. However, maintain the separation between input variables (the legal data) and prompt instructions to ensure consistent traceability.

Require Claude to place citations in brackets containing the search-index ID followed by a period, such as [1.]. This format, specified in 09_Complex_Prompts_from_Scratch.ipynb, creates a clear mapping between factual claims and their source materials within the <search_results> block.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →