Files
basically-ai-harness/agent/4-guardrails.ts
T
Tejas Kumar b29905a3ac Initial
2026-04-02 10:57:24 +02:00

59 lines
1.8 KiB
TypeScript

import type { ChatCompletionMessageParam } from "openai/resources/chat/completions";
type GuardrailInput = {
iterations: number;
messages: ChatCompletionMessageParam[];
};
export type GuardrailResult = { ok: true } | { ok: false; reason: string };
export type GuardrailFn = (input: GuardrailInput) => GuardrailResult;
// ── Individual guardrails ─────────────────────
// Stop after too many iterations — prevents infinite loops
const maxIterations =
(limit: number): GuardrailFn =>
({ iterations }) =>
iterations >= limit
? { ok: false, reason: `Guardrail: reached iteration limit (${limit})` }
: { ok: true };
// Stop if context has ballooned unexpectedly
const maxMessages =
(limit: number): GuardrailFn =>
({ messages }) =>
messages.length > limit
? { ok: false, reason: `Guardrail: context too large (${messages.length} messages)` }
: { ok: true };
// ── Compose into one fn ───────────────────────
export function combineGuardrails(...fns: GuardrailFn[]): GuardrailFn {
return (input) => {
for (const check of fns) {
const result = check(input);
if (!result.ok) return result;
}
return { ok: true };
};
}
// Stop after successful upvote
export const stopAfterUpvote =
(getUpvotedStory: () => { id: string; title?: string; rank?: number } | null): GuardrailFn =>
() => {
const story = getUpvotedStory();
if (story) {
const storyInfo = story.title && story.rank
? `"${story.title}" (rank ${story.rank})`
: `story ID ${story.id}`;
return { ok: false, reason: `Successfully upvoted ${storyInfo}` };
}
return { ok: true };
};
export const defaultGuardrails = combineGuardrails(
maxIterations(15),
maxMessages(50)
);