Filter Chains
Filter chains are Plano’s way of capturing reusable workflow steps in the dataplane, without duplication and coupling logic into application code. A filter chain is an ordered list of mutations that a request flows through before reaching its final destination —such as an agent, an LLM, or a tool backend. Each filter is a network-addressable service/path that can:
Inspect the incoming prompt, metadata, and conversation state.
Mutate or enrich the request (for example, rewrite queries or build context).
Short-circuit the flow and return a response early (for example, block a request on a compliance failure).
Emit structured logs and traces so you can debug and continuously improve your agents.
In other words, filter chains provide a lightweight programming model over HTTP for building reusable steps in your agent architectures.
Typical Use Cases
Without a dataplane programming model, teams tend to spread logic like query rewriting, compliance checks, context building, and routing decisions across many agents and frameworks. This quickly becomes hard to reason about and even harder to evolve.
Filter chains show up most often in patterns like:
Guardrails and Compliance: Enforcing content policies, stripping or masking sensitive data, and blocking obviously unsafe or off-topic requests before they reach an agent.
Query rewriting, RAG, and Memory: Rewriting user queries for retrieval, normalizing entities, and assembling RAG context envelopes while pulling in relevant memory (for example, conversation history, user profiles, or prior tool results) before calling a model or tool.
Cross-cutting Observability: Injecting correlation IDs, sampling traces, or logging enriched request metadata at consistent points in the request path.
Because these behaviors live in the dataplane rather than inside individual agents, you define them once, attach them to many agents and prompt targets, and can add, remove, or reorder them without changing application code.
Configuration example
The example below shows a configuration where an agent uses a filter chain with two filters: a query rewriter, and a context builder that prepares retrieval context before the agent runs.
1version: v0.3.0
2
3agents:
4 - id: rag_agent
5 url: http://host.docker.internal:10505
6
7filters:
8 - id: query_rewriter
9 url: http://host.docker.internal:10501
10 # type: mcp # default is mcp
11 # transport: streamable-http # default is streamable-http
12 # tool: query_rewriter # default name is the filter id
13 - id: context_builder
14 url: http://host.docker.internal:10502
15
16model_providers:
17 - model: openai/gpt-4o-mini
18 access_key: $OPENAI_API_KEY
19 default: true
20 - model: openai/gpt-4o
21 access_key: $OPENAI_API_KEY
22
23model_aliases:
24 fast-llm:
25 target: gpt-4o-mini
26 smart-llm:
27 target: gpt-4o
28
29listeners:
30 - type: agent
31 name: agent_1
32 port: 8001
33 router: arch_agent_router
34 agents:
35 - id: rag_agent
36 description: virtual assistant for retrieval augmented generation tasks
37 filter_chain:
38 - query_rewriter
39 - context_builder
40tracing:
41 random_sampling: 100
In this setup:
The
filterssection defines the reusable filters, each running as its own HTTP/MCP service.The
listenerssection wires therag_agentbehind anagentlistener and attaches afilter_chainwithquery_rewriterfollowed bycontext_builder.When a request arrives at
agent_1, Plano executes the filters in order before handing control torag_agent.
Filter Chain Programming Model (HTTP and MCP)
Filters are implemented as simple RESTful endpoints reachable via HTTP. If you want to use the Model Context Protocol (MCP), you can configure that as well, which makes it easy to write filters in any language. However, you can also write a filter as a plain HTTP service.
When defining a filter in Plano configuration, the following fields are optional:
type: Controls the filter runtime. Usemcpfor Model Context Protocol filters, orhttpfor plain HTTP filters. Defaults tomcp.transport: Controls how Plano talks to the filter (defaults tostreamable-httpfor efficient streaming interactions over HTTP). You can omit this for standard HTTP transport.tool: Names the MCP tool Plano will invoke (by default, the filterid). You can omit this if the tool name matches your filter id.
In practice, you typically only need to specify id and url to get started. Plano’s sensible defaults mean a filter can be as simple as an HTTP endpoint. If you want to customize the runtime or protocol, those fields are there, but they’re optional.
Filters communicate the outcome of their work via HTTP status codes:
HTTP 200 (Success): The filter successfully processed the request. If the filter mutated the request (e.g., rewrote a query or enriched context), those mutations are passed downstream.
HTTP 4xx (User Error): The request violates a filter’s rules or constraints—for example, content moderation policies or compliance checks. The request is terminated, and the error is returned to the caller. This is not a fatal error; it represents expected user-facing policy enforcement.
HTTP 5xx (Fatal Error): An unexpected failure in the filter itself (for example, a crash or misconfiguration). Plano will surface the error back to the caller and record it in logs and traces.
This semantics allows filters to enforce guardrails and policies (4xx) without blocking the entire system, while still surfacing critical failures (5xx) for investigation.
If any filter fails or decides to terminate the request early (for example, after a policy violation), Plano will surface that outcome back to the caller and record it in logs and traces. This makes filter chains a safe and powerful abstraction for evolving your agent workflows over time.