CrewAI Integration

Give CrewAI agents a cryptographic human approval gate before executing high-stakes tasks.

Key Concepts

The signedapproval-crewai package provides SignedApprovalCrewTool — a CrewAI BaseToolsubclass that blocks agent execution until a real human approves. The tool sends a push notification to the approver's phone and waits for a biometric-authenticated decision before returning.

Every approval produces an Ed25519 signature — unforgeable, offline-verifiable proof that a specific human authorized the action at a specific time.

Setup Guide
1

Install the package

bash
pip install signedapproval-crewai
# with CrewAI:
pip install "signedapproval-crewai[crewai]"
2

Get your API key

Create an API key in the Dashboard → API Keys. Store it as an environment variable.

bash
export SIGNEDAPPROVAL_API_KEY="sa_live_..."
3

Add the tool to your agent

python
import os
from crewai import Agent, Task, Crew
from signedapproval_crewai import SignedApprovalCrewTool

approval_tool = SignedApprovalCrewTool(
    api_key=os.environ["SIGNEDAPPROVAL_API_KEY"]
)

agent = Agent(
    role="Deployment Manager",
    goal="Deploy services safely with human oversight",
    backstory=(
        "You manage production deployments. For any deployment or "
        "destructive database operation, you MUST get human approval first."
    ),
    tools=[approval_tool],
    verbose=True,
)

deploy_task = Task(
    description=(
        "Deploy the payment service v2.1.0 to production. "
        "Use the signed_approval tool before making any changes."
    ),
    agent=agent,
    expected_output="Deployment status with approval signature.",
)

crew = Crew(agents=[agent], tasks=[deploy_task])
result = crew.kickoff()
print(result)

Multi-agent crew with approval gate

Use the approval tool in a multi-agent setup to gate transitions between agents:

python
from crewai import Agent, Task, Crew, Process
from signedapproval_crewai import SignedApprovalCrewTool

approval_tool = SignedApprovalCrewTool(api_key=os.environ["SIGNEDAPPROVAL_API_KEY"])

planner = Agent(
    role="Release Planner",
    goal="Prepare a deployment plan",
    backstory="...",
)

approver_agent = Agent(
    role="Approval Gatekeeper",
    goal="Request human sign-off before deployments proceed",
    backstory="You must use signed_approval for every production change.",
    tools=[approval_tool],
)

deployer = Agent(
    role="Deployer",
    goal="Execute approved deployments",
    backstory="Only deploy after you receive APPROVED from the gatekeeper.",
)

tasks = [
    Task(description="Plan the release of v2.1.0", agent=planner, expected_output="Release plan"),
    Task(description="Get human approval for the plan", agent=approver_agent, expected_output="APPROVED or REJECTED"),
    Task(description="Deploy if approved", agent=deployer, expected_output="Deployment result"),
]

crew = Crew(agents=[planner, approver_agent, deployer], tasks=tasks, process=Process.sequential)
crew.kickoff()

Tool output format

The tool returns a human-readable string that CrewAI passes to the next step. Example outputs:

text
# Approved:
APPROVED — Signature: dGhpcyBpcyBhIHRlc3Q... | Key: key_abc123 | Request: req_xyz

# Rejected:
REJECTED — The human declined this action.

# Expired (no decision within TTL):
EXPIRED — No decision was made within the time limit.

Instruct your agent to treat REJECTED and EXPIRED as a hard stop and not proceed with the action.

Important
CrewAI agents may attempt to continue a task after a rejection if not instructed otherwise. Include explicit instructions in the agent's backstory and task description to halt and report if the tool returns REJECTED.
Note
The SignedApprovalCrewTool works without installing crewai — it falls back to a plain Python object with the same _run() interface. This makes it usable in any agent framework that calls tools by invoking _run(action).