@agent-assistant/proactive

中文文档
0.4.37发布于 2026/10/04MITTypeScriptES Module构建来源已验证近 30 天下载 2.5万

Proactive decision engine for Agent Assistant SDK

原始使用文档
文档目录11 节
  1. What This Package Does
  2. Installation
  3. Quick Start
  4. Usage in a Capability Handler
  5. Follow-Up Rules
  6. Watch Rules
  7. Scheduler Binding
  8. Evidence Sources
  9. Reminder State Management
  10. What Stays Outside This Package
  11. Package Structure

@agent-assistant/proactive

Status: IMPLEMENTATION_READY Version: 0.1.0 (pre-1.0, provisional) Spec: docs/specs/v1-proactive-spec.md Implementation plan: docs/architecture/v1-proactive-implementation-plan.md


What This Package Does

@agent-assistant/proactive is the decision layer for proactive assistant behavior — any assistant action that originates without a direct user message in the current turn.

It provides:

  • ProactiveEngine — evaluates follow-up rules and watch rules against session context, applies suppression policy, and returns structured decisions
  • Follow-up rule evaluation — rules fire, suppress, or are silenced by cooldown/max-count/user-activity checks
  • Reminder policy — configurable maxReminders, cooldownMs, and suppressWhenActive per rule
  • Watch rules — long-running monitoring rules that re-schedule themselves after every evaluation; lifecycle methods for pause, resume, and cancel
  • SchedulerBinding interface — thin contract to external scheduling infrastructure (relaycron); this package does not own or wrap relaycron
  • InMemorySchedulerBinding — test adapter with a manual trigger helper; no external infrastructure required for tests
  • FollowUpEvidenceSource interface — optional pluggable evidence injection (e.g., memory entries) for rule conditions

This package does not own scheduling infrastructure, session lifecycle, message delivery, or domain-specific rule logic. All of that stays in product code or other packages.


Installation

npm install @agent-assistant/proactive

No @agent-assistant/* runtime dependencies. Only nanoid is required at runtime.


Quick Start

import {
  createProactiveEngine,
  InMemorySchedulerBinding,
} from '@agent-assistant/proactive';
import type { FollowUpRule } from '@agent-assistant/proactive';

// Wire a scheduler binding (InMemorySchedulerBinding for tests/dev)
const schedulerBinding = new InMemorySchedulerBinding();

const engine = createProactiveEngine({
  schedulerBinding,
  defaultReminderPolicy: {
    maxReminders: 3,
    cooldownMs: 3_600_000, // 1 hour
    suppressWhenActive: true,
  },
});

// Register a follow-up rule (stale-thread pattern)
const staleThreadRule: FollowUpRule = {
  id: 'stale-thread',
  description: 'Follow up if the session has been silent for more than 24 hours',
  condition: (ctx) => {
    const inactiveMs =
      new Date(ctx.scheduledAt).getTime() - new Date(ctx.lastActivityAt).getTime();
    return inactiveMs > 24 * 60 * 60 * 1000;
  },
  policy: {
    maxReminders: 2,
    cooldownMs: 24 * 60 * 60 * 1000,
  },
  routingHint: 'cheap',
  messageTemplate: 'Checking in — any updates on this thread?',
};

engine.registerFollowUpRule(staleThreadRule);

Usage in a Capability Handler

The proactive package does not register a capability handler. Products write their own:

// In your assistant definition (product code)
const definition = {
  capabilities: {
    proactive: async (message, context) => {
      const wakeUpContext = message.payload; // parsed from the synthetic wake-up message

      // Fetch session state from your session store
      const session = await context.sessionStore.get(wakeUpContext.sessionId);

      // Evaluate follow-up rules
      const decisions = await engine.evaluateFollowUp({
        sessionId: wakeUpContext.sessionId,
        scheduledAt: wakeUpContext.scheduledAt,
        lastActivityAt: session.lastActivityAt,
      });

      for (const decision of decisions) {
        if (decision.action === 'fire') {
          await context.runtime.emit({
            sessionId: decision.sessionId,
            text: decision.messageTemplate ?? 'Following up.',
          });
        }
      }
    },
  },
};

Follow-Up Rules

Rules are product-supplied. The engine handles watch-rule re-scheduling via SchedulerBinding and reminder state. Follow-up scheduling is product-owned.

interface FollowUpRule {
  id: string;
  condition(ctx: FollowUpEvaluationContext, evidence: EvidenceEntry[]): boolean | Promise<boolean>;
  description?: string;
  policy?: ReminderPolicy;       // overrides engine default when present
  routingHint?: 'cheap' | 'fast' | 'deep'; // defaults to 'cheap'
  messageTemplate?: string;
}

Suppression order:

  1. User became active after the wake-up was scheduled (lastActivityAt > scheduledAt)
  2. Max reminders reached for this (sessionId, ruleId) pair
  3. Cooldown window not elapsed since the last reminder
  4. Condition function returned false

The first matching suppression wins. If none match, the decision is fire.


Watch Rules

Watch rules are long-running monitors that re-schedule themselves after every evaluation — whether or not the condition triggered.

engine.registerWatchRule({
  id: 'unreviewed-pr',
  description: 'Alert if a PR has been open without review for over 2 hours',
  condition: async (ctx) => {
    // product fetches PR state from its own store
    return myStore.hasUnreviewedPRsOlderThan(2 * 60 * 60 * 1000);
  },
  action: { type: 'notify_channel', payload: { channel: 'eng-alerts' } },
  intervalMs: 30 * 60 * 1000, // check every 30 minutes
});

// Lifecycle
engine.pauseWatchRule('unreviewed-pr');
engine.resumeWatchRule('unreviewed-pr');
engine.cancelWatchRule('unreviewed-pr'); // permanent; re-register to restart

// List statuses
const statuses = engine.listWatchRules();
// [{ rule, status: 'active' | 'paused' | 'cancelled', lastEvaluatedAt, nextWakeUpBindingId }]

// Evaluate (called from your proactive capability handler after each wake-up)
const triggers = await engine.evaluateWatchRules({
  ruleId: wakeUpContext.ruleId,
  scheduledAt: wakeUpContext.scheduledAt,
  metadata: wakeUpContext.metadata,
});
for (const trigger of triggers) {
  await handleWatchAction(trigger.action, trigger.context);
}

Scheduler Binding

The SchedulerBinding interface decouples the engine from scheduling infrastructure.

interface SchedulerBinding {
  requestWakeUp(at: Date, context: WakeUpContext): Promise<string>; // returns bindingId
  cancelWakeUp(bindingId: string): Promise<void>;
}

For tests and local development: use the built-in InMemorySchedulerBinding:

const binding = new InMemorySchedulerBinding();

// Inspect pending wake-ups
console.log(binding.pendingWakeUps); // Map<bindingId, { at, context }>

// Manually fire a wake-up in tests
const context = await binding.trigger(bindingId);

For production: implement SchedulerBinding against your relaycron client. The proactive package does not implement or ship a relaycron integration — that is a product/foundation concern.


Evidence Sources

Optional. Wire an evidence source to give rule conditions access to recent memory entries or other context:

const evidenceSource = {
  getRecentEntries: (sessionId, opts) =>
    memoryStore.retrieve({ scope: { kind: 'session', sessionId }, limit: opts?.limit }),
};

const engine = createProactiveEngine({ schedulerBinding, evidenceSource });

If configured, the engine calls getRecentEntries once per evaluateFollowUp call (shared across all rules in that call). If context.evidence is pre-fetched and provided, the source is not called at all.

If not configured, condition functions receive an empty evidence array.


Reminder State Management

Reminder state is in-memory and keyed by (sessionId, ruleId).

// Clear state for a specific rule in a session (e.g., when user resolves the thread)
engine.resetReminderState('session-abc', 'stale-thread');

// Clear all reminder state for a session (e.g., on session close)
engine.resetReminderState('session-abc');

What Stays Outside This Package

ConcernWhere it lives
Scheduling infrastructure (timers, cron, dispatch)Relay foundation (relaycron)
Domain-specific rule definitionsProduct repos
Product-specific timing thresholdsProduct configuration
Memory persistence@agent-assistant/memory (via FollowUpEvidenceSource)
Session lifecycle@agent-assistant/sessions
Outbound message delivery@agent-assistant/surfaces + Relay runtime
Cross-agent coordination of proactive actions@agent-assistant/coordination (v1.2)
Proactive action rate limiting / budgets@agent-assistant/policy (v2)

Package Structure

packages/proactive/
  package.json        — nanoid runtime dep only
  tsconfig.json
  src/
    types.ts          — all exported types, interfaces, error classes
    proactive.ts      — createProactiveEngine factory and all engine logic
    index.ts          — public re-exports
    proactive.test.ts — 45 tests
  README.md

PROACTIVE_PACKAGE_DIRECTION_READY

版本与发布记录

@agent-assistant/proactive 共发布 68 个版本,首次发布于 2026/04/13;过去 12 个月发布了 68 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.4.37latest2026/10/041 个月前
0.4.362026/10/041 个月前
0.4.352026/05/235 个月前
0.4.332026/05/155 个月前
0.4.322026/05/125 个月前
0.4.312026/05/086 个月前

关于 @agent-assistant/proactive 的常见问题

@agent-assistant/proactive 是什么?

Proactive decision engine for Agent Assistant SDK

如何安装 @agent-assistant/proactive?

在项目目录运行 npm install @agent-assistant/proactive,或使用 pnpm add / yarn add / bun add。

@agent-assistant/proactive 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@agent-assistant/proactive 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@agent-assistant/proactive 可以商用吗?

@agent-assistant/proactive 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@agent-assistant/proactive 的下载量有多少?

根据 npm 官方下载统计,@agent-assistant/proactive 在 2026/10/05 – 2026/11/03 这 30 天内被下载 24,816 次,日均约 827 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@agent-assistant/proactive 还在维护吗?

最新版本 0.4.37 发布于 2026/10/04(1 个月前);至今共发布 68 个版本,其中过去 12 个月发布了 68 个;首次发布于 2026/04/13。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。