CrewAI decides who does what. AgentValet decides what they can reach.
A normal CrewAI tool holds the credential: to post to Slack, something in your process has a Slack token. With AgentValet the crew holds one identity key, and its tool list is built on the server from your grants, so a platform you haven’t granted produces no tool at all.
One pip install, one line in your crew
You need Python 3.10 or later. This path uses no MCP server and no Node at runtime.
Give the machine an agent identity. The register command prints four environment variables when it finishes. No Node?
pip install agentvaletand runagentvalet register --code <code>with an invite or enrolment code; it writes the key to~/.agentvalet/agent.keyand prints the ids.Terminal npx @agentvalet/registerSet
AGENT_IDandOWNER_IDwhere the crew runs, plusAGENT_PRIVATE_KEY_PATHif the key isn’t in~/.agentvalet/.Install the CrewAI package.
Terminal pip install crewai-agentvaletHand your agent the governed tools. There’s one tool per platform you’ve granted, and nothing else.
crew.py from crewai import Agent from crewai_agentvalet import governed_tools agent = Agent( role="Operations Engineer", goal="Keep the team informed", backstory="You handle routine ops chores end to end.", tools=governed_tools(), )Grant platforms in the dashboard. What you grant is exactly what the crew can see.
Use the MCP server instead
CrewAI speaks MCP too. Use the stdio server, not the remote URL: agent assertions last 60 seconds, and MCPServerHTTP sets its headers once, so a static token stops working a minute into the run. The stdio server signs a fresh assertion for every call.
Add the
mcps=block to any agent in the crew.crew.py from crewai import Agent from crewai.mcp import MCPServerStdio agent = Agent( role="Operations Engineer", goal="Keep the team informed and the tracker up to date", backstory="You handle routine ops chores end to end.", mcps=[MCPServerStdio( command="npx", args=["-y", "@agentvalet/mcp-server"], env={ "AGENT_ID": agent_id, "OWNER_ID": owner_id, "AGENT_PRIVATE_KEY_PATH": key_path, }, )], )
What’s governed here
Nothing is allowed until you grant it. This is a typical first grant for CrewAI; you decide every row, and you can change it without touching the agent.
Refusals come back to the agent as text it can reason about, not as exceptions that fail the task. When an approval is still pending, the tool tells the agent not to retry, because the action is already queued.
| What the agent tries | Platform | Decision |
|---|---|---|
| Read contacts | HubSpot | Allowed within grant |
| Post in #ops | Slack | Allowed within grant |
| Schedule a social post | Buffer | Asks you |
| Delete a contact | HubSpot | Not granted |
Different roles, different authority
Give each role its own agent when their authority should differ. A researcher that only reads and a publisher that can post are two identities with two grants, and the audit log then tells you which role did what.
Your CrewAI logs say what the agents decided to do. The audit log says what they were allowed to do, and what a human said when asked.
CrewAI guide in the docsThe longer walkthrough, kept with the product docs.
Put CrewAI behind AgentValet.
Register the agent, grant only what it needs, and approve the risky calls from your phone. Free to start, no credit card.