diff --git a/integrations/signet-signing/README.md b/integrations/signet-signing/README.md new file mode 100644 index 00000000..fdc35517 --- /dev/null +++ b/integrations/signet-signing/README.md @@ -0,0 +1,43 @@ +# CrewAI + Signet: Signed Tool Calls with Audit Trail + +This example shows how to add Ed25519 cryptographic signing to every +CrewAI tool call, producing a tamper-evident audit log. + +## Why + +- Prove which agent called which tool, with what parameters, and when +- Detect log tampering via SHA-256 hash chain +- Comply with SOC 2 / HIPAA audit requirements for AI agent actions + +## Setup + +```bash +pip install -r requirements.txt +``` + +## Run + +```bash +python main.py +``` + +## Verify the audit trail + +```bash +signet audit --since 1h +signet audit --verify +signet verify --chain +``` + +## How it works + +Signet hooks into CrewAI's `before_tool_use` / `after_tool_use` callbacks. +Every tool invocation is signed with the agent's Ed25519 key and appended +to a local hash-chained JSONL log at `~/.signet/audit/`. + +No infrastructure required. No network calls. Pure local crypto. + +## Learn more + +- [Signet GitHub](https://github.com/Prismer-AI/signet) +- [PyPI: signet-auth](https://pypi.org/project/signet-auth/) diff --git a/integrations/signet-signing/main.py b/integrations/signet-signing/main.py new file mode 100644 index 00000000..0a00c096 --- /dev/null +++ b/integrations/signet-signing/main.py @@ -0,0 +1,72 @@ +"""CrewAI + Signet: Sign every tool call with Ed25519.""" + +from crewai import Agent, Crew, Task +from crewai.tools import tool +from signet_auth import SigningAgent +from signet_auth.crewai import install_hooks, uninstall_hooks, get_receipts + + +@tool("search") +def search_tool(query: str) -> str: + """Search for information.""" + return f"Results for: {query}" + + +@tool("write_file") +def write_tool(filename: str, content: str) -> str: + """Write content to a file.""" + return f"Written to {filename}" + + +def main(): + # 1. Create a Signet identity + signer = SigningAgent.create("crew-bot", owner="demo", unencrypted=True) + + # 2. Install signing hooks (3 lines!) + install_hooks(signer, audit=True) + + # 3. Run your crew as usual + researcher = Agent( + role="Researcher", + goal="Find information about AI agent security", + backstory="You are a security researcher.", + tools=[search_tool], + ) + + writer = Agent( + role="Writer", + goal="Write a summary of the research", + backstory="You are a technical writer.", + tools=[write_tool], + ) + + task1 = Task( + description="Research MCP server security best practices", + expected_output="A list of security recommendations", + agent=researcher, + ) + + task2 = Task( + description="Write a summary of the security research", + expected_output="A written summary", + agent=writer, + ) + + crew = Crew(agents=[researcher, writer], tasks=[task1, task2]) + crew.kickoff() + + # 4. Check signed receipts + receipts = get_receipts() + print(f"\n{'='*60}") + print(f"Signed {len(receipts)} tool calls:") + for r in receipts: + print(f" {r.ts} {r.action.tool} sig={r.sig[:30]}...") + + # 5. Clean up + uninstall_hooks() + + print(f"\nVerify with: signet audit --since 1h --verify") + + +if __name__ == "__main__": + main() diff --git a/integrations/signet-signing/requirements.txt b/integrations/signet-signing/requirements.txt new file mode 100644 index 00000000..238b294e --- /dev/null +++ b/integrations/signet-signing/requirements.txt @@ -0,0 +1,2 @@ +crewai>=0.80 +signet-auth>=0.4.0