Amp Hooks
Akto Guardrails for Amp provides security validation for AI coding agent interactions. It intercepts prompts before the turn starts, tool calls before they execute, and tool results and responses after they complete — validating each against security policies, blocking risky behavior, and reporting events to your Akto dashboard.
Key Features
✅ Zero Installation - No standalone apps to install
✅ Transparent Integration - Uses Amp's native plugin mechanism
✅ Real-time Protection - Validates every prompt, tool call, tool result and response
✅ MCP Coverage - Tool calls are reported as JSON-RPC
tools/call, so MCP servers and tools show up in your inventory✅ Centralized Monitoring - All events reported to Akto dashboard
✅ Flexible Deployment - Supports Argus and Atlas modes
✅ Configurable Behavior - Blocking or observation modes
Amp has no shell-command hook mechanism. Unlike Claude CLI or Codex CLI, Amp cannot run a script on a lifecycle event. Its only interception point is a plugin — a TypeScript module loaded from .amp/plugins/ and executed by Bun. Akto therefore ships akto-guardrails-plugin.ts, a thin bridge that dispatches to the same Python validators every other Akto connector uses. There is no amp.hooks setting and no -wrapper.sh scripts.
Verified against Amp 0.0.1786968161.
How It Works
The plugin subscribes to five Amp lifecycle events — two around the conversation, two around every tool call, and one when a thread session starts:
5 Event Points:
session.start— Registers the thread session for observability. Cannot blockagent.start— Validates prompts before the turn starts. Blocks by callingthread.cancel(), which Amp documents as preventing the turn from startingtool.call— Validates tool input before execution. The only event that can stop a tool: it returnsreject-and-continuewith a reason, so the tool never runs and the model can choose another route. It can also returnmodifyto run the tool with guardrail-sanitized argumentstool.result— Validates tool output against response guardrails before it reaches the model. Blocks by replacing the result with an error, so sensitive file/shell/MCP output never enters the conversation. The tool has already run, so its side effects standagent.end— Validates the assistant's reply against response guardrails and records a violation as a 403. Reports but cannot block — see the limitation below
The prompt guardrail does not run in execute mode (amp -x). Amp does not emit agent.start in execute mode — verified against Amp 0.0.1786968161, where validate-prompt.log is never created for an amp -x run. Interactive Amp fires it normally.
The pending prompt is readable at session.start, but that event is fire-and-forget (it is not in PluginRequestResultMap), so Amp does not await it and a thread.cancel() from there cannot reliably pre-empt the turn. In execute mode, enforcement therefore happens at the tool layer — tool.call and tool.result, which Amp does await, and which are confirmed to block in amp -x.
Headless/CI runs that must screen prompts should validate them before invoking amp -x.
The assistant's response cannot be blocked — an Amp platform limit. agent.end fires after the turn finishes and its only result is { action: 'continue', userMessage }, which starts a new turn; the reply has already streamed to the user. The plugin API has no event between generation and display, and no redact, suppress, or message-edit capability (thread mutation is append-only). Verified against amp plugins show-docs and the Plugin API reference.
A sensitive response is therefore detected, flagged as a 403 in Guardrail Activity, and surfaced via an Amp notification — but not suppressed. To block responses, route inference through an AI gateway instead (amp config model-providers add-router openai-compatible --base-url <akto-gateway>), which puts Akto in the request path. That is a separate integration from these hooks.
File Structure
Key Files:
akto-guardrails-plugin.ts: The only file Amp loads. Subscribes to the five events, spawns the Python validators, and maps their decisions onto Amp's actions (thread.cancel(),reject-and-continue,modify)⚠️ Reads
~/.config/amp/akto/configfor the Akto URL and token — see the configuration step
Python scripts (
.py): Core validation logic and Akto API communication. The plugin resolves them relative to its own path, so they must sit in the same directoryakto-validate-pre-tool.py: Validates every tool call before it runs. Reports MCP calls (mcp__<server>__<tool>) as JSON-RPCtools/callon/mcp; can reject the call or rewrite its argumentsakto-validate-post-tool.py: Validates the tool result against response guardrails and can replace it with an error. Tool output is normalized to text first (shell_commandreturns{"output": ...}, MCP tools may return content blocks); mirroring those verbatim buries the text a level too deep and the guardrail never scans itakto-validate-response.py: Validates the assistant's reply against response guardrails and records a violation as a 403. Cannot block the replyakto_ingestion_utility.py: lives in theshared/GitHub directory, notamp-cli-hooks/, so it is fetched fromSHARED_BASE— miss it and session correlation degradesakto_heartbeat.py: Registers this device with Akto every 30s. Required — without a heartbeat record, mini-runtime cannot resolve the device to a user and drops every event before indexing, so the endpoint never appears under LLM observability / traces even though ingestion succeedsakto_machine_id.py: Generates unique device identifiers for Atlas mode
Setup Guide
Prerequisites
Amp CLI installed and authenticated (ampcode.com) — run
amp --versionto verifyAkto instance URL and API token
Python 3.7+ (standard library only — the validators need no third-party packages)
macOS, Linux, or Windows with bash/zsh
Installation Steps
Create Directories
Download the Plugin and Validators
For a single repository instead of system-wide, use <repo>/.amp/plugins/ as the destination.
Configure Akto Ingestion URL, API Token and Device ID ⚠️ CRITICAL STEP
Amp starts the plugin as a long-lived process and passes on only its own environment — a GUI-launched Amp does not inherit your shell profile. Use the config file so the install works regardless of how Amp was started. Obtain the API token from Akto Atlas → Connectors → Setup Guardrail card. If your deployment does not require auth, leave the token empty.
Environment variables of the same name still take precedence over the file, so a shell export can override any single value for a one-off run.
Reload Amp
Amp auto-discovers the plugin — no configuration entry is required. Open the command palette (Ctrl+O) and run plugins: reload, or restart Amp.
You should see akto-guardrails-plugin.ts active.
Configure MCP Servers (Optional)
MCP servers are registered in Amp's own settings. The plugin guards whatever is configured — no extra wiring.
Verify Installation
Test by running an Amp command that uses a tool:
You should see PLUGIN_INIT, SESSION_START, then VALIDATION_ALLOWED lines for akto-validate-pre-tool.py, akto-validate-post-tool.py and akto-validate-response.py.
PROMPT_ALLOWED will not appear here: agent.start does not fire in execute mode. To see the prompt guardrail, send a prompt in interactive Amp and look for AGENT_START followed by PROMPT_ALLOWED or PROMPT_BLOCKED.
Configuration Reference
Config File Variables
Read from ~/.config/amp/akto/config (override the path with AKTO_CONFIG_FILE). Every key can also be supplied as an environment variable, which takes precedence.
Mode Options:
Argus: Standard validation and reporting
Atlas: Includes device-specific metadata
Sync Mode:
true: Blocks threats (prompts, tool calls, tool output)
false: Reports but allows execution. Every event is still ingested — observe mode changes enforcement only, not coverage
Tool Event Variables
Read by akto-validate-pre-tool.py / akto-validate-post-tool.py. All optional — the defaults match what the enterprise installer configures.
Logging Variables
On-prem deployments must override DATABASE_ABSTRACTOR_SERVICE_URL. It defaults to the SaaS cyborg endpoint. If your Akto runs on-prem, point it at your own abstractor before the heartbeat can register the device — and until it registers, LLM observability and traces stay empty.
How DEVICE_ID is reported: the validators send <DEVICE_ID>.ai-agent.amp as the request host, and the dashboard uses the first label of that host as the device name. If DEVICE_ID is empty they fall back to the machine UUID — which is why a device sometimes shows up as a bare hex string.
Troubleshooting
Plugin Not Loading
Reload with the command palette (Ctrl+O → plugins: reload) or restart Amp. A PLUGIN_INIT line with "ingestionConfigured":false means the plugin started but found no AKTO_DATA_INGESTION_URL in the config file or environment — it stays inactive until that is set.
Nothing Is Being Validated
ModuleNotFoundError: No module named 'akto_ingestion_utility'
The shared ingestion utility was not downloaded, or landed outside the plugin directory. It lives in the shared/ directory on GitHub, not under HOOKS_BASE, so it needs its own curl.
If the file is present and the import still fails, check that PYTHONSAFEPATH is unset — it suppresses the script-directory entry on sys.path that this import relies on.
MCP Tool Calls Not Appearing
tool.call fires for every tool, but only names matching mcp__<server>__<tool> are reported as MCP tools/call on /mcp. Built-in tools (shell_command, apply_patch, …) take the non-MCP path and are not ingested unless you opt in.
If the log shows Processing built-in tool request, the call was not an MCP tool — that is expected for Amp's own tools.
Endpoint Appears in Inventory but Traces / LLM Observability Are Empty
Ingestion and trace indexing are separate paths. mini-runtime resolves each event's device to a user via the heartbeat record (moduleInfo.name → additionalData.username); an event whose device has no heartbeat, and which carries no user_email header, is discarded before indexing. Amp's plugin payloads never carry an email, so the heartbeat is the only thing that can satisfy this — the collection still shows up in inventory, which is why the endpoint looks connected.
If the file is missing, re-run the download step. If it is present but never sends, confirm DATABASE_ABSTRACTOR_SERVICE_URL points at a reachable abstractor (see the hint above) and that the token in ~/.config/amp/akto/config is valid — the publisher sends it as the Authorization header and swallows its own errors, so a rejected heartbeat is silent apart from the log line.
Prompt Blocks Are Not Visible in the Transcript
This is expected. Amp cannot reject a prompt inline, so a blocked prompt cancels the turn and the reason is delivered as an Amp notification. Confirm the block happened in the log:
A Prompt Was Not Blocked
First check whether the run was execute mode. agent.start does not fire under amp -x, so there is no prompt guardrail there (see the warning above) — validate-prompt.log will have no entry for that run at all.
No AGENT_START line means Amp never delivered the event. In interactive Amp you should see AGENT_START followed by PROMPT_ALLOWED or PROMPT_BLOCKED.
Something Was Reported but Not Blocked
Check the verdict before assuming the connector is at fault — it relays whatever Akto returns.
DENIEDbut the action went through — a connector problem, worth reportingALLOWED— no policy matched. Policies carryapplyOnRequestandapplyOnResponseflags plus acontextSourcescope, so a request-only policy will never block tool output or a reply, and a policy scoped to a different context source will not match at allALLOWEDon a call that took ~5s or more — the guardrails service can fail open internally under latency, returning "allowed" before any client timeout applies. Compare theDuration:line against a fast call with the same payload
Guardrails Time Out
Guardrail evaluation typically takes 1–2 seconds per call. If your policies are slower, raise the timeout — the plugin kills a validator that exceeds it and allows the action (fail-open).
Check Logs for Errors
The plugin log uses these event names:
PLUGIN_INIT
Plugin loaded. ingestionConfigured:false means no AKTO_DATA_INGESTION_URL was found
SESSION_START
Thread session started
AGENT_START
Prompt received. Absent in execute mode (amp -x)
PROMPT_ALLOWED / PROMPT_BLOCKED
Prompt verdict; blocked cancels the turn
TOOL_BLOCKED
Tool call rejected before running
TOOL_INPUT_MODIFIED
Tool ran with guardrail-sanitized arguments
TOOL_RESULT_BLOCKED
Tool output replaced with an error before reaching the model
RESPONSE_FLAGGED
Assistant reply violated policy — recorded, not suppressed
VALIDATION_TIMEOUT
Validator exceeded AKTO_TIMEOUT; the action was allowed (fail-open)
SCRIPT_NOT_FOUND
A .py file is missing from the plugin directory
Uninstallation
To completely remove Akto Guardrails from Amp:
Complete Removal
Selective Removal (Keep Logs)
Backup Before Removal
Verify Removal
Enterprise Deployment
Automated Deployment Script
Deploy to developers:
Quick Setup Summary
Resources
Amp Manual — Plugins: https://ampcode.com/manual#plugins
Amp Plugin API Reference: https://ampcode.com/manual/plugin-api
Support: support@akto.io
Community: https://www.akto.io/community
Last updated