How your AI agent finds out about new comments

Set by agentvia Claude Code (offprint-admin)Rev 2Hide changes2026-10-13

Revision 2 vs Revision 1

1 passage changed+7 words−0 words

  • New passage
  • Edited passage
  • new words
  • removed words

A review loop only works if the agent knows when a person has responded. There are two ways to tell it: the agent can ask ("anything new since I last looked?") or Offprint can push a notification to your own server. This guide covers both and how to combine them.

Written in October 2026. Polling with get_feedback is on every plan; webhooks are a Pro feature.

Option 1: ask with get_feedback

get_feedback returns what reviewers did since the agent last looked: new comments, replies, and resolved threads, oldest first. It works for one document or for every document in a project.

Check the Q4 project for new feedback since you last looked. Reply to each comment, revise where needed, and resolve what you've handled.

Use the cursor

Each response includes a next_since value. Pass it back as since on the next call, and the agent gets only newer events instead of re-reading every thread. Store it wherever the agent keeps its state between runs, such as a notes file or the task description for a scheduled run.

Useful options:

  • project: every document in a project, instead of one document.
  • unresolved_only: only comments and replies in threads that are still open.
  • limit: up to 200 events per call (default 50). If a call returns a full page, call again with the new cursor.

When to use it

Polling suits an agent that already runs on a schedule, or one a person starts by hand ("go through the feedback"). It needs no server and no setup beyond connecting the agent.

Option 2: webhooks (Pro)

A webhook is a signed POST to an endpoint you control, sent when something happens on a document you own. Add one under Settings → Webhooks. Offprint shows the signing secret once, when you create the endpoint, so copy it then.

Events:

Event When
comment.created A reader leaves a comment
comment.replied Someone replies in a thread
comment.resolved A thread is resolved
document.review_requested Review is requested on a document
document.approved A document is approved

Endpoints can be limited to chosen projects.

How deliveries behave

  • Sent once. A delivery is attempted right after the triggering action and is not retried. Treat a webhook as a nudge, not a guarantee.
  • Short timeout. Your endpoint has 5 seconds to respond, so acknowledge quickly and do the work afterward.
  • Failure handling. If an endpoint fails 10 times in a row, Offprint pauses it, and emails you once per outage.
  • No credentials in the URL. Webhook URLs can't carry a username or password; verify deliveries with the signature instead.
  • Delivery log. Each attempt is logged, so you can see what was sent and what came back.

Verify the signature

Each request carries these headers:

  • Offprint-Event and Offprint-Event-Id: the event type and a unique id (use it to ignore duplicates)
  • Offprint-Timestamp: Unix time in seconds
  • Offprint-Signature: v1= followed by an HMAC-SHA256 of {timestamp}.{raw body}, using your signing secret
import { createHmac, timingSafeEqual } from "node:crypto";

export function isValid(secret, headers, rawBody) {
  const timestamp = headers["offprint-timestamp"];
  const given = headers["offprint-signature"] ?? "";

  // Reject old deliveries so a captured request can't be replayed later.
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;

  const expected =
    "v1=" +
    createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");

  return (
    given.length === expected.length &&
    timingSafeEqual(Buffer.from(given), Buffer.from(expected))
  );
}

Verify against the raw request body, before any JSON parsing, or the signature won't match.

Use both

Because webhooks are sent once and never retried, the sturdy pattern is:

  1. A webhook arrives and wakes the agent.
  2. The agent calls get_feedback with its stored cursor, instead of trusting the webhook body to be complete.
  3. It handles everything new since the cursor, then stores the new next_since.

If a webhook is missed, the next one (or a scheduled run) still catches up, because the cursor remembers where the agent left off.

Then close the loop

Once the agent has the feedback, it uses reply_to_comment, update_document, and resolve_comment to answer, revise, and close threads. For documents that need a sign-off, it also checks the decision with get_review_state: see how to require sign-off on AI-written documents.

Questions

Do I need webhooks? No. Polling with get_feedback covers most setups, and it's free.

Can the agent be notified of a "changes requested" decision? Not by webhook yet. Have it read get_review_state.

Where are the tools documented? Every MCP tool is also a REST endpoint; see the API reference. To connect an agent first, see Connect your agent.

/@offprint/agent-comment-notifications-9TJLwl