/** Conversation scope a policy is resolved for. Absent means "agent scope". */ export type PolicyConversationType = 'direct' | 'group' | 'unknown'; export type ParticipationStyle = 'natural' | 'collaborative' | 'mention-first' | 'approval-gated' | 'handoff-only' | 'observer'; /** * The stored/parsed shape. This is the RETURN type of * {@link parseAgentBehaviorSettings} and {@link normalizeStoredAgentBehaviorPolicy}, * so its optional fields deliberately stay `T | undefined` — widening them to * `T | null` would be a breaking change for every reader of those results. * Parameter positions take {@link AgentBehaviorSettingsInput} instead. */ export interface AgentBehaviorSettingsRecord { participationStyle?: ParticipationStyle; allowAgentToAgent?: boolean; allowLongRunningCollaboration?: boolean; requireMentionForGroupReplies?: boolean; maxConsecutiveAgentTurns?: number | null; instructions?: string | null; } /** * The input shape accepted by {@link resolveAgentBehaviorPolicy}. Every field * additionally accepts an explicit `null` (an editor clearing a value), which * coalesces exactly like `undefined` — the field falls through to the next * layer. {@link AgentBehaviorSettingsRecord} is assignable to this type. */ export interface AgentBehaviorSettingsInput { participationStyle?: ParticipationStyle | null; allowAgentToAgent?: boolean | null; allowLongRunningCollaboration?: boolean | null; requireMentionForGroupReplies?: boolean | null; maxConsecutiveAgentTurns?: number | null; instructions?: string | null; } export interface ParticipationPolicy { style: ParticipationStyle; allowAgentToAgent: boolean; allowHumanToAgent: boolean; allowLongRunningCollaboration: boolean; requireMentionForGroupReplies: boolean; maxConsecutiveAgentTurns?: number | null; } export interface ResolvedAgentBehaviorPolicyRecord { participation: ParticipationPolicy; instructions: string[]; source: { hasAgentDefault: boolean; hasConversationOverride: boolean; }; } export interface ParticipationDecisionInput { conversationType: PolicyConversationType; senderType: 'human' | 'ai_agent'; isOwner: boolean; mentionedAgent: boolean; recentHumanCount?: number; /** * Consecutive agent turns already in the streak, NOT counting the message * being evaluated. The message itself adds one more when its sender is an * agent, and a delivery would add a further one — see the turn-cap check in * {@link evaluateParticipationPolicy}. */ consecutiveAgentTurns?: number; currentAgentStreakStartedByHuman?: boolean; } export interface ParticipationDecision { allow: boolean; reasonCode: string; reason: string; } export interface ParticipationHistoryMessage { id?: string; senderId: string; senderType: 'human' | 'ai_agent'; metadata?: unknown; } export interface ParticipationHistorySnapshot { recentSenderTypes: Array<'human' | 'ai_agent'>; recentHumanCount: number; recentAgentCount: number; consecutiveAgentTurns: number; currentAgentStreakStartedByHuman: boolean; } export declare const PARTICIPATION_HISTORY_FETCH_LIMIT = 50; /** * Safety backstop for conversations with no explicit turn cap: at most this * many consecutive agent turns before a human speaks or a new conversation * starts. * * This is a backstop, not the steering wheel — agents are expected to stop on * their own. Every triggerable agent message counts in both direct and group * conversations. An explicit `null` remains the deployer opt-out for trusted, * intentionally long-running collaboration. */ export declare const DEFAULT_GROUP_MAX_CONSECUTIVE_AGENT_TURNS = 4; export declare const DEFAULT_DIRECT_MAX_CONSECUTIVE_AGENT_TURNS = 4; export declare function parseAgentBehaviorSettings(raw: unknown): AgentBehaviorSettingsRecord; export declare function normalizeStoredAgentBehaviorPolicy(raw: Record | undefined): AgentBehaviorSettingsRecord | null; export declare function normalizeAgentBehaviorInstructions(value: string | null | undefined): string | null; /** * The scope-independent participation defaults. `maxConsecutiveAgentTurns` is * `null` here because the turn cap is scope-dependent — a conversation with no * stored setting resolves to its direct or group safety default. Use * {@link resolveAgentBehaviorPolicy} with a `conversationType` to learn what a * given conversation actually enforces. */ export declare function getDefaultParticipationPolicy(): ParticipationPolicy; /** * Coalesce agent defaults and a conversation override into the resolved record * every runtime reads. `conversationType` selects the Canon-wide fallbacks that * differ per scope — today only the turn cap, which defaults to 4 in direct and * group conversations and to unlimited elsewhere. Omit it when resolving for * the agent scope (no conversation); * an absent or unknown type always resolves to the unlimited default, so a call * site that forgets to thread it can never invent a cap. */ export declare function resolveAgentBehaviorPolicy(params?: { agentDefault?: AgentBehaviorSettingsInput | null; conversationOverride?: AgentBehaviorSettingsInput | null; conversationType?: PolicyConversationType; }): ResolvedAgentBehaviorPolicyRecord; export declare function buildParticipationHistorySnapshot(messages: ParticipationHistoryMessage[], agentId?: string): ParticipationHistorySnapshot; export declare function appendParticipationHistoryMessage(snapshot: ParticipationHistorySnapshot, message: ParticipationHistoryMessage, limit?: number): ParticipationHistorySnapshot; export declare function evaluateParticipationPolicy(policy: ResolvedAgentBehaviorPolicyRecord | null | undefined, input: ParticipationDecisionInput): ParticipationDecision;