| Crates.io | sentinel-agent-protocol |
| lib.rs | sentinel-agent-protocol |
| version | 0.4.2 |
| created_at | 2025-12-25 07:47:13.529088+00 |
| updated_at | 2026-01-21 20:01:04.906669+00 |
| description | Agent protocol and IPC for Sentinel reverse proxy external processors |
| homepage | https://github.com/raskell-io/sentinel |
| repository | https://github.com/raskell-io/sentinel |
| max_upload_size | |
| id | 2004319 |
| size | 874,954 |
A protocol crate for communication between the Sentinel proxy dataplane and external processing agents (WAF, auth, rate limiting, custom logic).
Inspired by SPOE (Stream Processing Offload Engine) and Envoy's ext_proc, designed for bounded, predictable behavior with strong failure isolation.
use sentinel_agent_protocol::{
AgentServer, AgentHandler, AgentResponse, Decision,
RequestHeadersEvent, RequestMetadata,
};
use async_trait::async_trait;
struct MyAgent;
#[async_trait]
impl AgentHandler for MyAgent {
async fn on_request_headers(&self, event: RequestHeadersEvent) -> AgentResponse {
// Block requests to /admin
if event.uri.starts_with("/admin") {
return AgentResponse::block(403, "Forbidden");
}
AgentResponse::default_allow()
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let server = AgentServer::new(
"my-agent",
"/tmp/my-agent.sock",
Box::new(MyAgent),
);
server.run().await?;
Ok(())
}
use sentinel_agent_protocol::{AgentClient, EventType, RequestHeadersEvent};
use std::time::Duration;
// Unix socket transport
let mut client = AgentClient::unix_socket(
"proxy",
"/tmp/my-agent.sock",
Duration::from_secs(5),
).await?;
// Or gRPC transport
let mut client = AgentClient::grpc(
"proxy",
"http://localhost:50051",
Duration::from_secs(5),
).await?;
// Send an event
let response = client.send_event(EventType::RequestHeaders, &event).await?;
| Property | Value |
|---|---|
| Protocol Version | 1 |
| Max Message Size | 10 MB |
| UDS Message Format | 4-byte big-endian length prefix + JSON payload |
| gRPC Format | Protocol Buffers over HTTP/2 |
The protocol supports 8 event types covering the full request/response lifecycle:
| Event | Description | Typical Use |
|---|---|---|
Configure |
Initial handshake with agent capabilities | Feature negotiation |
RequestHeaders |
Request headers received | Auth, routing, early blocking |
RequestBodyChunk |
Request body chunk (streaming) | Body inspection, transformation |
ResponseHeaders |
Response headers from upstream | Header modification |
ResponseBodyChunk |
Response body chunk (streaming) | Response transformation |
RequestComplete |
Request fully processed | Logging, cleanup |
WebSocketFrame |
WebSocket frame received | Message filtering |
GuardrailInspect |
Content inspection request | Prompt injection, PII detection |
Agents respond with one of four decisions:
| Decision | Description | Fields |
|---|---|---|
Allow |
Continue processing | - |
Block |
Reject the request | status, body, headers |
Redirect |
Redirect to another URL | url, status (301/302/307/308) |
Challenge |
Issue a challenge | challenge_type, params |
Detailed documentation is available in the docs/ directory:
┌─────────────────┐ ┌─────────────────┐
│ Sentinel Proxy │ │ External Agent │
│ (Dataplane) │ │ (WAF/Auth/ │
│ │ │ Custom Logic) │
│ ┌───────────┐ │ UDS/ │ ┌───────────┐ │
│ │AgentClient│◄─┼─gRPC───►│ │AgentServer│ │
│ └───────────┘ │ │ └─────┬─────┘ │
│ │ │ │ │
└─────────────────┘ │ ┌─────▼─────┐ │
│ │AgentHandler│ │
│ └───────────┘ │
└─────────────────┘
See Architecture & Flow Diagrams for detailed diagrams including:
Two reference agents are included for testing and as implementation examples:
Adds an X-Agent-Processed: true header to all requests. Useful for verifying agent connectivity.
use sentinel_agent_protocol::{AgentServer, EchoAgent};
let server = AgentServer::new("echo", "/tmp/echo.sock", Box::new(EchoAgent));
Blocks requests matching configured paths or client IPs.
use sentinel_agent_protocol::{AgentServer, DenylistAgent};
let agent = DenylistAgent::new(
vec!["/admin".to_string(), "/internal".to_string()],
vec!["10.0.0.1".to_string()],
);
let server = AgentServer::new("denylist", "/tmp/denylist.sock", Box::new(agent));
Official SDKs are available for building agents in your preferred language:
| Language | Repository | Installation |
|---|---|---|
| Python | sentinel-agent-python-sdk | pip install sentinel-agent-sdk |
| TypeScript | sentinel-agent-typescript-sdk | npm install sentinel-agent-sdk |
| Go | sentinel-agent-go-sdk | go get github.com/raskell-io/sentinel-agent-go-sdk |
| Rust | sentinel-agent-rust-sdk | sentinel-agent-sdk = "0.1" |
| Elixir | sentinel-agent-elixir-sdk | {:sentinel_agent_sdk, github: "raskell-io/sentinel-agent-elixir-sdk"} |
All SDKs implement the same protocol and provide:
See the main Sentinel repository for license information.