InkdownInkdown
Start writing

Study

59 filesยท8 subfolders

Shared Workspace

Study
core

19_BEST_PRACTICES

Shared from "Study" on Inkdown

Best Practices - Comprehensive Deep Dive

Overview

This document compiles the best practices for using the OpenAI Agents Python SDK. These practices are distilled from real-world usage, community feedback, and the core development team's experience. Following these practices will help you build robust, maintainable, and efficient agent-based applications.

General Principles

1. Start Simple

Begin with simple agents and add complexity gradually:

Python
# Good - start simple
agent = Agent(
    name="assistant",
    instructions="You are a helpful assistant",
)

# Avoid - start complex
agent = Agent(
    name="complex",
    instructions="...",
    tools=[...],
    guardrails=[...],
    handoffs=[...],
    hooks=...,
    # Too much complexity from the start
)
programming-language-concepts.md
zero-language-explanation.md
DB
01-introduction.md
02-relational-databases.md
03-database-design.md
04-indexing.md
05-transactions-acid.md
06-nosql-databases.md
07-query-optimization.md
08-replication-ha.md
09-sharding-partitioning.md
10-caching-strategies.md
11-cap-theorem.md
12-connection-pooling.md
13-backup-recovery.md
14-monitoring.md
15-database-selection.md
README.md
JS
Event loop
Merlin Backend
01-Orchestration.md
02-DeepResearch.md
03-Search.md
04-Scraping.md
05-Streaming.md
06-MultiProviderLLM.md
07-MemoryAndContext.md
08-ErrorHandling.md
09-RateLimiting.md
10-TaskQueue.md
11-SecurityAndAuth.md
Orchestration-2nd-draft
OpenAI Agents Python
00_OVERVIEW.md
01_AGENT_SYSTEM.md
02_RUNNER_SYSTEM.md
03_TOOL_SYSTEM.md
04_ITEMS_SYSTEM.md
05_GUARDRAILS.md
06_HANDOFFS.md
07_MEMORY_SESSIONS.md
08_MODEL_PROVIDERS.md
09_SANDBOX_SYSTEM.md
10_TRACING.md
11_RUN_STATE.md
12_CONTEXT.md
13_LIFECYCLE_HOOKS.md
14_CONFIGURATION.md
15_ERROR_HANDLING.md
16_STREAMING.md
17_EXTENSIONS.md
18_MCP_INTEGRATION.md
19_BEST_PRACTICES.md
20_ARCHITECTURE_PATTERNS.md
opencode-study
context-handling
core
Python
Alembic
Basics
sqlalchemy - fastapi
SQLAlchemy overview
tweets
system_design_for_agentic_apps.md
2. Iterate Quickly

Build, test, and iterate quickly:

Python
# Start with basic version
agent = Agent(instructions="Basic instructions")
result = await Runner.run(agent, input)

# Add tools based on needs
agent = Agent(instructions="...", tools=[tool1])
result = await Runner.run(agent, input)

# Add more as needed
agent = Agent(instructions="...", tools=[tool1, tool2])
3. Use Type Hints

Always use type hints for better IDE support and type safety:

Python
# Good
@function_tool
def calculate(a: int, b: int) -> int:
    return a + b

# Avoid
@function_tool
def calculate(a, b):
    return a + b
4. Write Clear Instructions

Write clear, specific agent instructions:

Python
# Good
agent = Agent(
    name="summarizer",
    instructions=(
        "You are a summarization expert. Given a text, provide a concise summary "
        "in 3 bullet points. Each bullet point should be under 20 words. "
        "Focus on the main ideas and ignore minor details."
    ),
)

# Avoid
agent = Agent(
    name="vague",
    instructions="Summarize things",  # Too vague
)
5. Test Thoroughly

Test your agents extensively:

Python
@pytest.mark.asyncio
async def test_agent_basic():
    """Test basic agent behavior."""
    result = await Runner.run(agent, "Hello")
    assert result.final_output is not None

@pytest.mark.asyncio
async def test_agent_with_tools():
    """Test agent with tools."""
    result = await Runner.run(agent, "Use the tool")
    assert "tool" in result.final_output.lower()

Agent Design

1. Single Responsibility

Each agent should have a single, clear responsibility:

Python
# Good - focused agents
coder = Agent(name="coder", instructions="Write code")
researcher = Agent(name="researcher", instructions="Research topics")
writer = Agent(name="writer", instructions="Write content")

# Avoid - multi-purpose agent
generalist = Agent(
    name="generalist",
    instructions="Write code, research topics, and write content",
)
2. Clear Naming

Use descriptive agent names:

Python
# Good
agent = Agent(name="customer_support_triage")

# Avoid
agent = Agent(name="agent1")  # Not descriptive
3. Appropriate Instructions

Match instructions to the agent's purpose:

Python
# Good
coder = Agent(
    name="coder",
    instructions=(
        "You are a senior software engineer. Write clean, well-documented code "
        "following best practices. Include error handling and type hints."
    ),
)

# Avoid
coder = Agent(
    name="coder",
    instructions="You are helpful",  # Too generic
)
4. Tool Selection

Only include relevant tools:

Python
# Good - relevant tools
coder = Agent(
    name="coder",
    instructions="Write code",
    tools=[read_file_tool, write_file_tool, execute_code_tool],
)

# Avoid - irrelevant tools
coder = Agent(
    name="coder",
    instructions="Write code",
    tools=[web_search_tool, email_tool, calendar_tool],  # Irrelevant
)
5. Handoff Descriptions

Write clear handoff descriptions:

Python
# Good
specialist = Agent(
    name="billing_specialist",
    instructions="Handle billing issues",
    handoff_description=(
        "Billing specialist for handling payment issues, refunds, "
        "subscription management, and account balance inquiries"
    ),
)

# Avoid
specialist = Agent(
    name="billing",
    instructions="Handle billing",
    handoff_description="Billing",  # Too vague
)

Tool Design

1. Clear Names

Use descriptive tool names:

Python
# Good
@function_tool
def search_academic_papers(query: str) -> str:
    ...

# Avoid
@function_tool
def search(q: str) -> str:  # Not descriptive
2. Type Hints

Always use type hints:

Python
# Good
@function_tool
def process_data(
    user_id: str,
    limit: int = 10,
    filters: Optional[List[str]] = None,
) -> str:
    ...

# Avoid
@function_tool
def process_data(user_id, limit=10, filters=None):  # No type hints
3. Docstrings

Write clear docstrings:

Python
# Good
@function_tool
def calculate_discount(price: float, discount_percent: float) -> float:
    """
    Calculate the discounted price.
    
    Args:
        price: The original price.
        discount_percent: The discount percentage (0-100).
    
    Returns:
        The discounted price.
    
    Example:
        calculate_discount(100.0, 20) returns 80.0
    """
    return price * (1 - discount_percent / 100)

# Avoid
@function_tool
def calculate_discount(price: float, discount_percent: float) -> float:
    """Calculate discount."""  # Too vague
4. Error Handling

Handle errors gracefully:

Python
# Good
@function_tool
def api_call(endpoint: str) -> str:
    """Call an API endpoint."""
    try:
        response = requests.get(endpoint)
        response.raise_for_status()
        return response.text
    except requests.RequestException as e:
        return f"API error: {str(e)}"

# Avoid
@function_tool
def api_call(endpoint: str) -> str:
    """Call an API endpoint."""
    return requests.get(endpoint).text  # No error handling
5. Input Validation

Validate inputs:

Python
# Good
@function_tool
def divide(a: float, b: float) -> float:
    """Divide two numbers."""
    if b == 0:
        raise ValueError("Cannot divide by zero")
    return a / b

# Avoid
@function_tool
def divide(a: float, b: float) -> float:
    """Divide two numbers."""
    return a / b  # Will crash on b=0

Guardrails

1. Use Appropriate Guardrails

Use guardrails at the right level:

Python
# Good - input guardrail for filtering
@input_guardrail
def check_safety(input):
    if "harmful" in input.lower():
        return GuardrailFunctionOutput(tripwire_triggered=True)
    return GuardrailFunctionOutput(tripwire_triggered=False)

# Good - output guardrail for validation
@output_guardrail
def check_length(output):
    if len(output) > 1000:
        return GuardrailFunctionOutput(tripwire_triggered=True)
    return GuardrailFunctionOutput(tripwire_triggered=False)
2. Clear Tripwire Conditions

Make it clear when guardrails trigger:

Python
# Good
@input_guardrail
def check_profanity(input):
    if has_profanity(input):
        return GuardrailFunctionOutput(
            output_info="Profanity detected",
            tripwire_triggered=True,
        )
    return GuardrailFunctionOutput(
        output_info="No profanity",
        tripwire_triggered=False,
)

# Avoid
@input_guardrail
def check(input):
    # Complex, unclear logic
    return GuardrailFunctionOutput(tripwire_triggered=some_complex_check(input))
3. Descriptive Output Info

Provide helpful output info:

Python
# Good
return GuardrailFunctionOutput(
    output_info="Query too short: minimum 3 characters, got 2",
    tripwire_triggered=True,
)

# Avoid
return GuardrailFunctionOutput(
    output_info="Error",
    tripwire_triggered=True,
)
4. Parallel When Possible

Use parallel execution for independent checks:

Python
# Good - independent checks
@input_guardrail(run_in_parallel=True)
def check_length(input):
    ...

@input_guardrail(run_in_parallel=True)
def check_content(input):
    ...

# Avoid - sequential when not needed
@input_guardrail(run_in_parallel=False)
def check_length(input):
    ...
5. Handle Errors Gracefully

Guardrails should handle their own errors:

Python
# Good
@input_guardrail
def safe_check(input):
    try:
        result = external_api.check(input)
        return GuardrailFunctionOutput(
            output_info=str(result),
            tripwire_triggered=result.is_flagged,
        )
    except Exception as e:
        logger.error(f"Guardrail error: {e}")
        return GuardrailFunctionOutput(
            output_info="Guardrail error, allowing input",
            tripwire_triggered=False,
        )

# Avoid
@input_guardrail
def unsafe_check(input):
    return external_api.check(input)  # If this fails, run fails

Configuration

1. Environment-Based Configuration

Use different configs for different environments:

Python
# Good
def get_config():
    env = os.getenv("ENVIRONMENT", "dev")
    
    if env == "production":
        return RunConfig(model="gpt-4o", tracing_disabled=False)
    else:
        return RunConfig(model="gpt-4o-mini", tracing_disabled=True)

# Avoid - hardcoded config
config = RunConfig(model="gpt-4o")  # Same for all environments
2. Configuration Files

Store configuration in files:

Python
# config.yaml
model: "gpt-4o"
temperature: 0.7
max_turns: 20

# Load config
with open("config.yaml") as f:
    config_data = yaml.safe_load(f)

config = RunConfig(
    model=config_data["model"],
    model_settings=ModelSettings(temperature=config_data["temperature"]),
)
3. Sensitive Data in Environment

Never hardcode sensitive data:

Python
# Good
api_key = os.getenv("OPENAI_API_KEY")

# Avoid
api_key = "sk-..."  # Never hardcode
4. Validate Configuration

Validate configuration early:

Python
# Good
config = get_config()
if not validate_config(config):
    raise ValueError("Invalid configuration")

result = await Runner.run(agent, input, run_config=config)

# Avoid
result = await Runner.run(agent, input, run_config=get_config())  # Might be invalid
5. Document Configuration

Document configuration options:

Python
"""
Configuration for agent runs.

Environment variables:
- MODEL: Model to use (default: gpt-4o)
- TEMPERATURE: Temperature (default: 0.7)
- MAX_TURNS: Maximum turns (default: 10)
"""

Context

1. Use Dataclasses

Use dataclasses for context:

Python
# Good
@dataclass
class MyContext:
    user_id: str
    data: dict

# Avoid
class MyContext:
    def __init__(self, user_id, data):
        self.user_id = user_id
        self.data = data
2. Keep Context Focused

Keep context focused on relevant data:

Python
# Good - focused context
@dataclass
class UserContext:
    user_id: str
    preferences: dict

# Avoid - bloated context
@dataclass
class EverythingContext:
    user_id: str
    preferences: dict
    database_connection: Any  # Don't put heavy resources here
    cache: dict
    logger: Any
3. Use Type Hints

Always use type hints:

Python
# Good
@dataclass
class MyContext:
    user_id: str
    data: dict[str, Any]

# Avoid
@dataclass
class MyContext:
    user_id  # No type hint
    data
4. Document Context Fields

Document context fields:

Python
# Good
@dataclass
class MyContext:
    """Context for user operations."""
    
    user_id: str
    """Unique identifier for the user."""
    
    preferences: dict
    """User preferences (theme, language, etc.)."""

# Avoid
@dataclass
class MyContext:
    user_id: str  # What is this?
    preferences: dict  # What keys?
5. Avoid Circular Dependencies

Avoid circular references in context:

Python
# Good - no circular references
@dataclass
class ContextA:
    data: str

@dataclass
class ContextB:
    context_a: ContextA

# Avoid - circular reference
@dataclass
class ContextA:
    context_b: ContextB

@dataclass
class ContextB:
    context_a: ContextA

Error Handling

1. Catch Specific Exceptions

Catch specific exceptions:

Python
# Good
try:
    result = await Runner.run(agent, input)
except MaxTurnsExceeded:
    handle_max_turns()
except InputGuardrailTripwireTriggered:
    handle_guardrail()

# Avoid
try:
    result = await Runner.run(agent, input)
except Exception:  # Too broad
    handle_all()
2. Provide Context in Errors

Include helpful context:

Python
# Good
raise UserError(
    f"Invalid model: {model_name}. "
    f"Valid models: {', '.join(VALID_MODELS)}"
)

# Avoid
raise UserError("Invalid model")
3. Log Before Raising

Log errors before re-raising:

Python
# Good
try:
    result = await Runner.run(agent, input)
except AgentsException as e:
    logger.error(f"Agent error: {e}", exc_info=True)
    raise

# Avoid
try:
    result = await Runner.run(agent, input)
except AgentsException as e:
    raise  # Lost logging opportunity
4. Use Custom Error Types

Define custom error types:

Python
class MyApplicationError(AgentsException):
    """Base error for my application."""
    pass

class InsufficientCreditsError(MyApplicationError):
    """Error when user has insufficient credits."""
    pass
5. Handle Errors Gracefully

Provide graceful fallbacks:

Python
# Good
try:
    result = await Runner.run(primary_agent, input)
except Exception:
    result = await Runner.run(fallback_agent, input)

# Avoid
result = await Runner.run(primary_agent, input)  # Might crash

Performance

1. Use Async

Always use async for production:

Python
# Good
result = await Runner.run(agent, input)

# Avoid in production
result = Runner.run_sync(agent, input)
2. Set Reasonable Limits

Set reasonable limits:

Python
# Good
config = RunConfig(
    max_turns=10,
    session_settings=SessionSettings(max_items=50),
)

# Avoid - no limits
config = RunConfig()  # Might run forever or use too many tokens
3. Use Appropriate Models

Choose the right model for the task:

Python
# Good - appropriate model
quick_agent = Agent(model="gpt-4o-mini")  # Fast, cheap

complex_agent = Agent(model="gpt-4o")  # More capable

# Avoid - overkill
simple_task = Agent(model="gpt-4o")  # Unnecessary expense
4. Enable Tracing Selectively

Enable tracing when needed:

Python
# Good
if environment == "production":
    config = RunConfig(tracing_disabled=False)
else:
    config = RunConfig(tracing_disabled=True)

# Avoid
config = RunConfig(tracing_disabled=True)  # No observability
5. Use Sessions for Long Conversations

Use sessions to manage conversation history:

Python
# Good
session = SQLiteSession(db_path="conversations.db")
result = await Runner.run(agent, input, session=session)

# Avoid - no session for long conversations
result = await Runner.run(agent, input)  # Token waste

Security

1. Validate Inputs

Validate all inputs:

Python
# Good
@function_tool
def process_data(user_id: str, data: dict):
    if not re.match(r'^[a-zA-Z0-9_]+$', user_id):
        raise ValueError("Invalid user_id")
    ...

# Avoid
@function_tool
def process_data(user_id: str, data: dict):
    ...  # No validation
2. Use Guardrails

Use guardrails for safety:

Python
# Good
agent = Agent(
    input_guardrails=[safety_check],
    output_guardrails=[quality_check],
)

# Avoid
agent = Agent()  # No safety checks
3. Require Approval for Sensitive Tools

Require approval for sensitive operations:

Python
# Good
@function_tool(needs_approval=True)
def delete_file(path: str):
    ...

# Avoid
@function_tool
def delete_file(path: str):
    ...  # Auto-executes
4. Exclude Sensitive Data from Traces

Exclude sensitive data from traces:

Python
# Good
config = RunConfig(
    trace_include_sensitive_data=False,
)

# Avoid
config = RunConfig(
    trace_include_sensitive_data=True,  # Leaks sensitive data
)
5. Use Environment Variables

Store secrets in environment variables:

Python
# Good
api_key = os.getenv("API_KEY")

# Avoid
api_key = "secret-key"  # Hardcoded

Testing

1. Test All Code Paths

Test all scenarios:

Python
# Good
@pytest.mark.asyncio
async def test_success_case():
    result = await Runner.run(agent, "Hello")
    assert result.final_output is not None

@pytest.mark.asyncio
async def test_error_case():
    with pytest.raises(MaxTurnsExceeded):
        await Runner.run(agent, "loop_forever")

# Avoid - only test happy path
@pytest.mark.asyncio
async def test_agent():
    result = await Runner.run(agent, "Hello")
    assert result.final_output is not None
2. Use Fixtures

Use fixtures for common setup:

Python
# Good
@pytest.fixture
def agent():
    return Agent(instructions="Test agent")

@pytest.mark.asyncio
async def test_with_fixture(agent):
    result = await Runner.run(agent, "Hello")
    assert result.final_output is not None

# Avoid - duplicate setup
@pytest.mark.asyncio
async def test1():
    agent = Agent(instructions="Test agent")
    ...

@pytest.mark.asyncio
async def test2():
    agent = Agent(instructions="Test agent")  # Duplicate
    ...
3. Mock External Dependencies

Mock external services:

Python
# Good
@pytest.mark.asyncio
async def test_with_mock():
    with patch('external_api.call') as mock:
        mock.return_value = "mocked result"
        result = await Runner.run(agent, "Use API")
        assert "mocked" in result.final_output

# Avoid - no mocking
@pytest.mark.asyncio
async def test_without_mock():
    result = await Runner.run(agent, "Use API")  # Calls real API
4. Test Edge Cases

Test edge cases:

Python
# Good
@pytest.mark.asyncio
async def test_empty_input():
    result = await Runner.run(agent, "")
    assert result.final_output is not None

@pytest.mark.asyncio
async def test_very_long_input():
    result = await Runner.run(agent, "a" * 10000)
    assert result.final_output is not None

# Avoid - only test normal cases
@pytest.mark.asyncio
async def test_normal_case():
    result = await Runner.run(agent, "Hello")
    assert result.final_output is not None
5. Test Configuration

Test with different configurations:

Python
# Good
@pytest.mark.asyncio
async def test_with_fast_config():
    config = RunConfig(model="gpt-4o-mini", max_turns=5)
    result = await Runner.run(agent, input, run_config=config)
    assert result.final_output is not None

# Avoid - always use default config
@pytest.mark.asyncio
async def test_with_default():
    result = await Runner.run(agent, input)
    assert result.final_output is not None

Documentation

1. Document Agent Purpose

Document what each agent does:

Python
# Good
"""
Customer Support Triage Agent

This agent triages customer support requests and routes them to
appropriate specialists based on the issue type.
"""
agent = Agent(
    name="triage",
    instructions="Triage customer support requests...",
)

# Avoid - no documentation
agent = Agent(name="triage", instructions="...")
2. Document Tools

Document tool behavior:

Python
# Good
@function_tool
def calculate_discount(price: float, discount_percent: float) -> float:
    """
    Calculate the discounted price.
    
    This function calculates the price after applying a discount percentage.
    It validates that the discount is between 0 and 100.
    
    Args:
        price: The original price (must be positive).
        discount_percent: The discount percentage (0-100).
    
    Returns:
        The discounted price.
    
    Raises:
        ValueError: If price is negative or discount is out of range.
    
    Example:
        >>> calculate_discount(100.0, 20)
        80.0
    """
    ...

# Avoid
@function_tool
def calculate_discount(price: float, discount_percent: float) -> float:
    """Calculate discount."""
    ...
3. Document Configuration

Document configuration options:

Python
# Good
"""
Configuration for agent runs.

Environment Variables:
    - MODEL: Model to use (default: gpt-4o)
    - TEMPERATURE: Temperature (default: 0.7)
    - MAX_TURNS: Maximum turns (default: 10)

Configuration Files:
    - config.yaml: Main configuration file
"""

# Avoid - no documentation
config = RunConfig(...)
4. Document Extensions

Document extension behavior:

Python
# Good
"""
Custom Memory Backend

This extension provides custom memory storage using XYZ database.

Configuration:
    - connection_string: Database connection string
    - table_name: Table name for storage

Usage:
    session = CustomMemorySession(
        connection_string="postgresql://...",
        table_name="agent_sessions",
    )
"""

# Avoid - no documentation
class CustomMemorySession(SessionABC):
    ...
5. Document API

Document public API:

Python
# Good
def run_agent(agent: Agent, input: str) -> str:
    """
    Run an agent with the given input.
    
    This is a convenience function that creates a runner and executes
    the agent with default configuration.
    
    Args:
        agent: The agent to run.
        input: The input to provide to the agent.
    
    Returns:
        The final output from the agent.
    
    Raises:
        AgentsException: If the agent run fails.
    
    Example:
        >>> agent = Agent(instructions="You are helpful")
        >>> run_agent(agent, "Hello")
        'Hello! How can I help you?'
    """
    ...

# Avoid - no documentation
def run_agent(agent, input):
    ...

Monitoring

1. Track Metrics

Track key metrics:

Python
# Good
from prometheus_client import Counter

agent_runs = Counter("agent_runs_total", "Total agent runs", ["agent_name"])
agent_errors = Counter("agent_errors_total", "Total agent errors", ["error_type"])

agent_runs.labels(agent_name=agent.name).inc()

# Avoid - no metrics
result = await Runner.run(agent, input)
2. Log Important Events

Log important events:

Python
# Good
logger.info(f"Agent {agent.name} started", extra={"run_id": run_id})
logger.info(f"Agent {agent.name} completed", extra={"duration": duration})

# Avoid - no logging
result = await Runner.run(agent, input)
3. Monitor Performance

Monitor performance metrics:

Python
# Good
from prometheus_client import Histogram

run_duration = Histogram("agent_run_duration_seconds", "Agent run duration")

start = time.time()
result = await Runner.run(agent, input)
duration = time.time() - start
run_duration.observe(duration)

# Avoid - no monitoring
result = await Runner.run(agent, input)
4. Alert on Errors

Alert on critical errors:

Python
# Good
try:
    result = await Runner.run(agent, input)
except CriticalError as e:
    await send_alert(f"Critical error: {e}")
    raise

# Avoid - no alerting
result = await Runner.run(agent, input)
5. Use Tracing

Use tracing for observability:

Python
# Good
config = RunConfig(
    tracing_disabled=False,
    workflow_name="Customer Support",
    trace_metadata={"user_id": user_id},
)

result = await Runner.run(agent, input, run_config=config)

# Avoid - no tracing
result = await Runner.run(agent, input)

Deployment

1. Use Environment Variables

Use environment variables for configuration:

Python
# Good
api_key = os.getenv("OPENAI_API_KEY")
model = os.getenv("MODEL", "gpt-4o")

# Avoid - hardcoded
api_key = "sk-..."
model = "gpt-4o"
2. Graceful Shutdown

Handle graceful shutdown:

Python
# Good
async def shutdown():
    """Graceful shutdown."""
    logger.info("Shutting down...")
    await cleanup_resources()
    logger.info("Shutdown complete")

# Avoid - no cleanup
# Process just killed
3. Health Checks

Implement health checks:

Python
# Good
@app.get("/health")
async def health_check():
    """Health check endpoint."""
    try:
        # Check agent health
        await test_agent()
        return {"status": "healthy"}
    except Exception as e:
        return {"status": "unhealthy", "error": str(e)}

# Avoid - no health checks
4. Resource Limits

Set resource limits:

Python
# Good
config = RunConfig(
    max_turns=10,
    session_settings=SessionSettings(max_items=50),
)

# Avoid - no limits
config = RunConfig()
5. Rate Limiting

Implement rate limiting:

Python
# Good
from slowapi import Limiter

limiter = Limiter(key_func=get_user_id)

@app.post("/run")
@limiter.limit("10/minute")
async def run_agent_endpoint(request):
    """Run agent with rate limiting."""
    ...

# Avoid - no rate limiting
@app.post("/run")
async def run_agent_endpoint(request):
    ...

Summary

Following these best practices will help you:

  1. Build robust agents that handle errors gracefully
  2. Maintain code that is easy to understand and modify
  3. Scale applications that perform well under load
  4. Secure systems that protect sensitive data
  5. Monitor applications with good observability
  6. Test code that catches bugs early
  7. Document code that others can understand
  8. Deploy applications reliably

Remember that best practices evolve with experience. Start with these guidelines, learn from your own experience, and adapt them to your specific use cases.