CrewAI Tutorial (Python): implementing guardrails for advanced developers

By Cyprian AaronsUpdated 2026-04-21
crewaiimplementing-guardrails-for-advanced-developerspython

This tutorial shows you how to add guardrails to a CrewAI workflow so bad inputs get blocked, bad outputs get rejected, and your agent only returns responses that match your contract. You need this when you’re moving beyond demos and into systems where a malformed answer, unsafe action, or policy violation is expensive.

What You'll Need

  • Python 3.10+
  • crewai
  • crewai-tools
  • pydantic
  • An OpenAI API key set as OPENAI_API_KEY
  • Basic familiarity with CrewAI agents, tasks, and crews
  • A local virtual environment

Install the packages:

pip install crewai crewai-tools pydantic

Set your API key:

export OPENAI_API_KEY="your-key-here"

Step-by-Step

  1. Start by defining a strict output schema. Guardrails work best when the task has a clear contract, because validation becomes deterministic instead of fuzzy.
from pydantic import BaseModel, Field

class RiskSummary(BaseModel):
    decision: str = Field(description="APPROVE or REJECT")
    confidence: float = Field(ge=0.0, le=1.0)
    reason: str = Field(min_length=20)
  1. Add a guardrail function that validates both structure and policy. In this example, we reject any response that doesn’t match the schema or contains a low-confidence approval.
from typing import Tuple

def risk_guardrail(result) -> Tuple[bool, str]:
    try:
        data = result if isinstance(result, dict) else result.model_dump()
        parsed = RiskSummary(**data)
    except Exception as e:
        return False, f"Invalid output schema: {e}"

    if parsed.decision == "APPROVE" and parsed.confidence < 0.85:
        return False, "Approval confidence too low"

    return True, "OK"
  1. Build an agent and attach the guardrail to the task. The important part here is that the task expects structured output, and the guardrail runs after generation but before your app consumes it.
from crewai import Agent, Task, Crew
from crewai.llm import LLM

llm = LLM(model="gpt-4o-mini")

analyst = Agent(
    role="Risk Analyst",
    goal="Assess loan applications with strict policy adherence",
    backstory="You produce concise underwriting decisions.",
    llm=llm,
)

task = Task(
    description=(
        "Review this applicant: income=$120000, debt=$30000, "
        "credit_score=720. Return APPROVE or REJECT."
    ),
    expected_output="A JSON object matching RiskSummary",
    agent=analyst,
    output_pydantic=RiskSummary,
    guardrail=risk_guardrail,
)
  1. Run the crew and inspect the validated result. If the model violates your rules, CrewAI will surface the guardrail failure instead of letting unsafe data flow downstream.
crew = Crew(
    agents=[analyst],
    tasks=[task],
)

result = crew.kickoff()
print(result)
print(type(result))
  1. For advanced workflows, use retries on failed guardrails instead of failing immediately. This is useful when you want the model to self-correct after being told exactly what was wrong.
task_with_retry = Task(
    description="Review this applicant: income=$65000, debt=$42000, credit_score=610.",
    expected_output="A JSON object matching RiskSummary",
    agent=analyst,
    output_pydantic=RiskSummary,
    guardrail=risk_guardrail,
    max_retries=2,
)

retry_crew = Crew(agents=[analyst], tasks=[task_with_retry])
retry_result = retry_crew.kickoff()
print(retry_result)

Testing It

Run the script once with a normal underwriting prompt and confirm you get a RiskSummary-shaped result back. Then intentionally weaken the prompt or modify the guardrail threshold to force a rejection; you should see CrewAI stop the bad output from being accepted.

If you want a stronger test, change expected_output to something vague and keep output_pydantic plus guardrail in place. The schema should still hold because validation is enforced in code, not by prompt wording.

Also test retry behavior by lowering max_retries and making the task harder to satisfy. You want to verify that failures are explicit and predictable instead of silently passing through.

Next Steps

  • Add input guardrails before task execution for PII redaction and prompt injection detection.
  • Chain multiple tasks with separate schemas so each step has its own validation boundary.
  • Log guardrail failures to your observability stack so policy violations are auditable in production.

Keep learning

By Cyprian Aarons, AI Consultant at Topiax.

Want the complete 8-step roadmap?

Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.

Get the Starter Kit

Related Guides