Integrate Highflame with Aperture
Last validated:
Highflame is a security and observability platform for AI workloads. By connecting Aperture to Highflame, you can enforce request policies before data reaches the provider and observe completed requests for auditing and threat detection.
Aperture sends data to Highflame using the hooks system. You configure a hook endpoint for your Highflame deployment and a grant that specifies which requests trigger the hook and what data to include.
Highflame supports both synchronous hooks (pre_request) for enforcement and asynchronous hooks (tool_call_entire_request / entire_request) for observability, through the same endpoint and API key. You can use one or both modes depending on your requirements. For a standalone pre-request guardrail without Highflame, refer to guardrails.
Prerequisites
Before you begin, you need the following:
- A running Aperture instance accessible from your device.
- A Highflame account with an API key. You can generate an API key from the Highflame console.
Configure the Highflame hook
Configure a hook in Aperture that points to your Highflame endpoint. This hook sends request data to Highflame for enforcement or observation.
-
Open the Aperture dashboard at
http://<aperture-hostname>/ui/. -
Select the Settings page and open the JSON editor.
-
Add a
highflameentry in thehookssection with your Highflame endpoint URL and API key."hooks": { "highflame": { "url": "<highflame-endpoint-url>", "apikey": "<highflame-api-key>", "timeout": "1s", "fail_policy": "fail_closed" } }Replace
<highflame-endpoint-url>with the URL of your Highflame endpoint and<highflame-api-key>with the API key from your Highflame console.timeoutsets the maximum time Aperture waits for a response. Forpre_requesthooks, keep this short (500ms to 2s) to limit client-visible latency. Asynchronous hooks are not latency-sensitive, but a timeout prevents stalled connections.fail_policycontrols what happens when Aperture cannot reach the endpoint.fail_closedblocks the request if Highflame is unavailable, which is appropriate when using Highflame for enforcement. Usefail_openif requests should proceed when Highflame is down, or if you use Highflame only for asynchronous observability.
After adding the hook, continue in the JSON editor to connect it to incoming requests using a grant.
Wire the hook to a grant
Connect the Highflame hook to incoming requests using a grant with a send_hooks entry. Highflame supports three modes depending on whether you need enforcement, observability, or both.
Synchronous enforcement (pre_request)
Use pre_request to have Highflame inspect requests before they reach the provider. Highflame returns allow or block (never modify) for each request.
"grants": [
{
"src": ["*"],
"app": {
"tailscale.com/cap/aperture": [
{
"send_hooks": [
{
"name": "highflame",
"events": ["pre_request"],
"send": ["request_body", "user_message"]
}
]
}
]
}
}
]
The send array controls what data Aperture includes in the hook payload. request_body is the full request body, and user_message is the last message the user sent.
Asynchronous observability (tool_call_entire_request)
Use tool_call_entire_request or entire_request to send completed request data to Highflame for auditing and threat detection after the response completes. Asynchronous hooks do not block or modify requests.
"grants": [
{
"src": ["*"],
"app": {
"tailscale.com/cap/aperture": [
{
"send_hooks": [
{
"name": "highflame",
"events": ["tool_call_entire_request"],
"send": ["tools", "user_message", "request_body", "response_body"]
}
]
}
]
}
}
]
The asynchronous hook includes additional data: tools contains tool declarations from the request, and response_body is the full response from the provider. Use tool_call_entire_request to send data only for requests that include tool calls, or entire_request to send data for all requests.
Combined enforcement and observability
To use both modes, include two send_hooks entries in the same grant. Both reference the same highflame hook definition.
"grants": [
{
"src": ["*"],
"app": {
"tailscale.com/cap/aperture": [
{
"send_hooks": [
{
"name": "highflame",
"events": ["pre_request"],
"send": ["request_body", "user_message"]
},
{
"name": "highflame",
"events": ["tool_call_entire_request"],
"send": ["tools", "user_message", "request_body", "response_body"]
}
]
}
]
}
}
]
If you define grants in a tailnet policy file instead of the Aperture JSON editor, each grant must include a dst key specifying which Aperture nodes the grant applies to. Refer to the configuration reference for details.
After adding the grant, save the configuration.
For details on hook events and send types, refer to the hooks configuration reference.
Verify the integration
After you configure the Highflame hook, verify that Aperture sends data to Highflame and that Highflame processes it correctly.
- Send a request through Aperture that matches your grant conditions. If you use
tool_call_entire_request, the request must include a tool call to trigger the hook. - If using
pre_requestmode, confirm the request is allowed or blocked as expected based on your Highflame policies. - Open the Highflame console and confirm the request data appears in the dashboard.
- If using asynchronous mode, verify that completed request data (including tool calls, if applicable) appears after the response completes.
If data doesn't appear, check that the send_hooks name matches the key in your hooks section and that the grant's src field includes the user who made the request.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Request passes through without being blocked | Hook uses entire_request or tool_call_entire_request instead of pre_request | Asynchronous hooks cannot block requests. Switch to pre_request for enforcement. |
| Highflame returns a timeout error | timeout value is too short for your network path | Increase the timeout value in the hook definition. For pre_request hooks, keep it under 2s to limit client-visible latency. |
| Request blocked when Highflame is unreachable | fail_policy is set to fail_closed | Change to fail_open if requests should proceed when Highflame is unavailable. Keep fail_closed if enforcement is mandatory. |
| Asynchronous data missing tool call details | send array does not include tools or response_body | Add the required fields to the send array in your grant's send_hooks entry. |
| API key rejected by Highflame | API key expired or belongs to a different environment | Generate a new API key from the Highflame console and update the apikey field in the hook definition. |
Security considerations
When you connect Aperture to Highflame, request content, including user messages, tool calls, and response bodies, travels to the Highflame endpoint in plaintext over your network path. Consider the following:
- Content exposure. The
sendarray in your grant controls what data Highflame receives. Include only the data types Highflame needs for your use case. For enforcement-only setups,request_bodyanduser_messageare sufficient. - API key handling. Store the Highflame API key securely. Aperture stores the key in its configuration and sends it as a header with each hook request. Rotate keys periodically from the Highflame console.
- Network path. Hook requests travel over your tailnet. Ensure the Highflame endpoint is accessible from your Aperture instance and that no intermediate services log or cache the request payload.
- Data scope. Use the
srcfield in your grants to limit which users' requests Aperture sends to Highflame. Avoid sending data for users who are not subject to your enforcement or observability policies.
Next steps
- Build a custom webhook to send Aperture data to other services.
- Learn about hook events and data types in the configuration reference.
- Explore other external integrations for Aperture.