Guard modes
Choose whether Featherlane AI blocks, rewrites, or asks the model to regenerate unsafe drafts.
The shortest TypeScript integration decorates the agent once. Python supports the equivalent function decorator.
import featherlane_ai
@featherlane_ai.guarded(agent_id="support-agent")
async def answer(message: str) -> str:
return await agent.reply(message)import { GuardMode, guardAgent } from '@featherlane-ai/sdk';
const agent = guardAgent(createAgent(), {
agentId: 'support-agent',
mode: GuardMode.Rewrite,
});
const reply = await agent.reply(userText);Modes
| Mode | Python | TypeScript | Behavior |
|---|---|---|---|
| Strict | GuardMode.STRICT | GuardMode.Strict | Blocks unsafe drafts immediately. |
| Rewrite | GuardMode.REWRITE | GuardMode.Rewrite | Uses Featherlane AI safe_output; blocks if no safe output exists. |
| Rewrite or regenerate | GuardMode.REWRITE_OR_REGENERATE | GuardMode.RewriteOrRegenerate | Uses safe_output; otherwise calls your regenerate function and guards the new draft. |
rewrite is the default mode.
Strict
Use strict mode for compliance-heavy workflows where unsafe output should never be rephrased by the agent.
guardrail = featherlane_ai.guard(
agent_id="support-agent",
mode=featherlane_ai.GuardMode.STRICT,
)const guardrail = guard({
agentId: 'support-agent',
mode: GuardMode.Strict,
});Rewrite
Use rewrite mode when Featherlane AI can provide the replacement text.
guardrail = featherlane_ai.guard(
agent_id="support-agent",
mode=featherlane_ai.GuardMode.REWRITE,
)const guardrail = guard({
agentId: 'support-agent',
mode: GuardMode.Rewrite,
});Rewrite Or Regenerate
Use regeneration when you want the model to try again in real time if Featherlane AI cannot provide a safe replacement.
async def regenerate_reply(feedback: featherlane_ai.RegenerateFeedback) -> str:
return await model.generate(
instructions=(
"The previous draft was blocked by Featherlane AI: "
f"{feedback.reason}. Generate a safer answer."
)
)
guardrail = featherlane_ai.guard(
agent_id="support-agent",
mode=featherlane_ai.GuardMode.REWRITE_OR_REGENERATE,
regenerate=regenerate_reply,
max_regenerations=1,
)const guardrail = guard({
agentId: 'support-agent',
mode: GuardMode.RewriteOrRegenerate,
maxRegenerations: 1,
regenerate: async (feedback) => {
return await model.generate({
instructions:
`The previous draft was blocked by Featherlane AI: ${feedback.reason}. ` +
'Generate a safer answer.',
});
},
});The SDK guards the regenerated draft again before returning it. Keep
max_regenerations / maxRegenerations low to avoid loops and latency spikes.
Choosing A Mode
Use strict when the safest answer is to stop or hand off. Use rewrite when
low latency matters and Featherlane AI safe output is acceptable. Use
rewrite_or_regenerate when a better model answer is worth one extra model
call.
Streaming output
When your model produces a token stream, use the guard's streaming form. It buffers the full stream, then guards the complete output and returns the guarded string — it never returns unguarded chunks, the same buffer-then-guard contract the gateway uses. All guard modes and callbacks apply unchanged.
const guardrail = guard({ agentId: 'support-agent' });
async function* tokens() {
for await (const chunk of model.stream(prompt)) yield chunk.text;
}
const reply = await guardrail.stream({ input: userText, draft: tokens() });guardrail = featherlane_ai.guard(agent_id="support-agent")
async def tokens():
async for chunk in model.stream(prompt):
yield chunk.text
reply = await guardrail.stream(input=user_text, draft=tokens())stream accepts any async (or sync) iterable of string chunks. For Rust
in-process pipelines, tl-stream's StreamingChecker accumulates a sliding
window and interrupts the moment an evaluator returns a non-permit effect.