Skip to main content

CrewAI tool for EnigmAgent — agents resolve {{PLACEHOLDER}} secrets at the call boundary so LLMs never see real API keys

Project description

crewai-tools-enigmagent

CI PyPI version PyPI downloads Python License: MIT CrewAI EnigmAgent GitHub stars

A CrewAI crew of three agents — researcher, writer, GitHub-poster — needs a GITHUB_TOKEN to publish the final post to a private repo. CrewAI's recommended pattern is to attach the token to the Agent's LLM config, or pass it through the task description. Both options bake the real token into the prompt context that travels through every model call. If any of those LLM calls is logged, traced, or shipped to a managed provider, the token is now in someone else's database.

crewai-tools-enigmagent is the alternative.

Your crew agent emits {{GITHUB_TOKEN}}. The placeholder rides through the LLM context, through the tool input, through every CrewAI trace. Only when the agent calls EnigmAgentTool does the placeholder get swapped for the real ghp_... value — locally, against an AES-256-GCM encrypted vault, and only if the requesting origin matches the secret's bound domain.

pip install crewai-tools-enigmagent

In another terminal, next to your crew:

npx enigmagent-mcp --mode rest --port 3737

That's the install. The Python package talks to the local EnigmAgent REST server over loopback; secrets stay in the encrypted vault on disk.

Star the main project if you've ever pasted a token you regretted.


The problem (in CrewAI terms)

When you give a CrewAI agent a credential, you have three options and all three leak:

Option What happens
Put the token into the Agent's goal or task description It lands in every LLM call the agent makes, in the trace, in the provider's logs
Bake the token into a custom tool at construction time The agent can call the tool with arbitrary inputs and exfiltrate the value indirectly
Inject via env var read inside the tool Works, but you have one long-lived plaintext token sitting in os.environ for the whole crew run

crewai-tools-enigmagent is option D. Your tasks, your prompts, your traces all carry only {{PLACEHOLDER}} strings. The real value is resolved at the boundary, by a process the model cannot see, against a vault on the user's machine.


How it works

┌──────────────────┐  emits {{GITHUB_TOKEN}}  ┌─────────────────────┐
│ CrewAI Agent     │ ───────────────────────▶ │  EnigmAgentTool     │
│ (any LLM)        │   + origin parameter     │  ._run(...)         │
└──────────────────┘                          └──────────┬──────────┘
                                                         │ HTTP POST /resolve
                                                         ▼
                                          ┌─────────────────────────┐
                                          │      EnigmAgent         │
                                          │  validates origin,      │
                                          │  decrypts AES-256-GCM   │
                                          │  → ghp_xxx              │
                                          └──────────┬──────────────┘
                                                     │ real value
                                                     ▼
                                          ┌─────────────────────────┐
                                          │  Agent uses value in    │
                                          │  next tool / API call   │
                                          └─────────────────────────┘

The model emits a placeholder name + the destination origin. The placeholder lives in the prompt and the trace. EnigmAgentTool._run() asks the local EnigmAgent REST server to swap it for the real value — but only if the request's origin matches the domain that secret was bound to. Wrong domain → the resolver refuses.


Usage

from crewai import Agent, Crew, Task
from crewai_tools_enigmagent import EnigmAgentTool

enigmagent = EnigmAgentTool()

github_op = Agent(
    role="GitHub Operator",
    goal=(
        "Open a GitHub issue on https://api.github.com using the credentials "
        "stored under the placeholder GITHUB_TOKEN. "
        "Always call the EnigmAgent tool with placeholder='GITHUB_TOKEN' and "
        "origin='https://api.github.com' to retrieve the token; never paste "
        "the raw token into your reasoning."
    ),
    backstory="You operate at the call boundary — secrets stay in the vault.",
    tools=[enigmagent],
)

task = Task(
    description="Open issue 'CI is red' in repo Agnuxo1/example.",
    expected_output="The URL of the created issue.",
    agent=github_op,
)

crew = Crew(agents=[github_op], tasks=[task])
result = crew.kickoff()

The agent's reasoning now contains only the placeholder name GITHUB_TOKEN and the origin https://api.github.com. The plaintext ghp_... exists for the duration of the upstream HTTP call and nowhere else.

Custom client config

from crewai_tools_enigmagent import EnigmAgentClient, EnigmAgentTool

client = EnigmAgentClient(
    base_url="http://127.0.0.1:9999",      # custom port
    timeout=5.0,
    shared_secret="my-loopback-token",      # sent as X-EnigmAgent-Auth header
)

enigmagent = EnigmAgentTool(client=client)

To run the EnigmAgent REST server with a shared secret:

npx enigmagent-mcp --mode rest --port 3737 --auth my-loopback-token

The vault

This package is a thin CrewAI wrapper. The real work — Argon2id key derivation, AES-256-GCM encryption, origin binding, audit logging — lives in EnigmAgent, the npm package that backs it.

# Create a vault interactively (one-time)
npx enigmagent-mcp --new-vault ./my.vault.json

# Add a secret bound to a domain
npx enigmagent-mcp --vault ./my.vault.json --add GITHUB_TOKEN ghp_xxx --origin https://api.github.com

# Run as REST server next to your CrewAI app
npx enigmagent-mcp --mode rest --port 3737 --vault ./my.vault.json

Security model

  • Loopback only. The REST server binds to 127.0.0.1. Only processes on the same machine can reach it.
  • Origin binding. Every secret is bound to one or more origins (e.g. https://api.github.com). Resolving a secret for a different origin is refused.
  • Argon2id + AES-256-GCM. The vault file is encrypted at rest with a passphrase-derived key.
  • No plaintext in prompts or traces. The agent's LLM context contains only {{PLACEHOLDER}} strings. Resolved values exist only inside the tool's return value, briefly, in the agent's local memory.
  • Optional shared secret. Pass --auth to require an X-EnigmAgent-Auth header on every REST call, so unauthorised local processes can't query the vault.

Full threat model: EnigmAgent THREAT_MODEL.md


Compatibility

  • Python: 3.10, 3.11, 3.12, 3.13
  • crewai >= 0.40
  • pydantic >= 2
  • Any LLM provider supported by CrewAI (OpenAI, Anthropic, Mistral, Gemini, local via Ollama)

Roadmap

  • EnigmAgentSubstituteTool that takes a templated string with multiple {{PLACEHOLDERS}} and substitutes them all in one call
  • Optional integration with CrewAI Flows to inject secrets at flow-state boundaries
  • Upstream proposal to crewai-tools once this package has real users

PRs welcome.


License

MIT (c) 2026 Francisco Angulo de Lafuente

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

crewai_tools_enigmagent-0.1.0.tar.gz (7.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

crewai_tools_enigmagent-0.1.0-py3-none-any.whl (8.1 kB view details)

Uploaded Python 3

File details

Details for the file crewai_tools_enigmagent-0.1.0.tar.gz.

File metadata

  • Download URL: crewai_tools_enigmagent-0.1.0.tar.gz
  • Upload date:
  • Size: 7.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for crewai_tools_enigmagent-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3429b651b2431b5b150b81ec385a2cc8e6465134ee77d64de16c53e60bb250f2
MD5 fc81bce91a4d89248bfd9aacd1806a28
BLAKE2b-256 509c788ff440afb4c8a8252af10cb1e708fbe0aa99d3f0746b161c1848fa592f

See more details on using hashes here.

File details

Details for the file crewai_tools_enigmagent-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for crewai_tools_enigmagent-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3fda8678ad85cfa24c2541979709d36f8ab48378adecc8e1b560b0920a6d65bf
MD5 74fc9705353d2b65e60cedac3ce923ac
BLAKE2b-256 9d30cc2c1a102e918715979939302af8c4e300a4c3e395464e04eb961a7f799d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page