Featherlane AI
Guides

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

ModePythonTypeScriptBehavior
StrictGuardMode.STRICTGuardMode.StrictBlocks unsafe drafts immediately.
RewriteGuardMode.REWRITEGuardMode.RewriteUses Featherlane AI safe_output; blocks if no safe output exists.
Rewrite or regenerateGuardMode.REWRITE_OR_REGENERATEGuardMode.RewriteOrRegenerateUses 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.

On this page