Quickstart Guide
This guide shows you how to register the three Notion Workers and make your first calls.
Worker Registration
All three workers are registered in src/index.ts using the @notionhq/workers Worker class:
import { Worker } from "@notionhq/workers" ;
import { executeWriteAgentDigest } from "./workers/write-agent-digest.js" ;
import { executeCheckUpstreamStatus } from "./workers/check-upstream-status.js" ;
import { executeCreateHandoffMarker } from "./workers/create-handoff-marker.js" ;
const worker = new Worker ();
// Register write-agent-digest
worker . tool ( "write-agent-digest" , {
title: "Write Agent Digest" ,
description: "Creates a governance-compliant agent digest or report page in the Docs database." ,
schema: writeDigestSchema ,
execute : ( input , context ) => executeWriteAgentDigest ( input , context . notion ),
});
// Register check-upstream-status
worker . tool ( "check-upstream-status" , {
title: "Check Upstream Status" ,
description: "Finds the most recent digest page for a given agent and returns structured status." ,
schema: checkUpstreamStatusSchema ,
execute : ( input , context ) => executeCheckUpstreamStatus ( input , context . notion ),
});
// Register create-handoff-marker
worker . tool ( "create-handoff-marker" , {
title: "Create Handoff Marker" ,
description: "Creates a structured handoff record when an agent escalates to another." ,
schema: createHandoffMarkerSchema ,
execute : ( input , context ) => executeCreateHandoffMarker ( input , context . notion ),
});
export default worker ;
Start the Worker
Run the worker locally:
Default
.env.local
1Password
Alternatively, run the entry file directly:
Worker 1: write-agent-digest
Creates a governance-compliant digest page with proper status lines, section ordering, and validation.
Example: Successful Sync Run
const input = {
agent_name: "GitHub Insyncerator" ,
agent_emoji: "🔄" ,
status_type: "sync" ,
status_value: "complete" ,
run_time_chicago: "2026-02-28T09:00:00-06:00" ,
scope: "All open PRs and recent commits in tracked repos" ,
input_versions: "None" ,
flagged_items: [
{
description: "PR #42 needs review" ,
task_link: "https://www.notion.so/task-abc123" ,
no_task_reason: ""
},
{
description: "Spike in failed CI on main" ,
task_link: "https://www.notion.so/task-def456" ,
no_task_reason: ""
},
],
actions_taken: {
created_tasks: [
{ name: "Review PR #42" , notion_url: "https://www.notion.so/task-abc123" }
],
updated_tasks: [
{ name: "Investigate CI failures" , notion_url: "https://www.notion.so/task-def456" }
],
},
summary: "Synced 3 repos. 2 items flagged, 1 escalation to Client Repo Auditor." ,
needs_review: [],
escalations: [
{
escalated_to: "Client Repo Auditor" ,
escalation_reason: "Spike in CI failures may need client repo audit" ,
escalation_owner: "Client Repo Auditor" ,
handoff_complete: false ,
},
],
target_database: "docs" ,
doc_type: "Agent Digest" ,
client_relation_ids: [],
project_relation_ids: [],
};
// Call the worker
const result = await worker . execute ( input );
// Returns: { success: true, page_url: "https://notion.so/...", title: "🔄 GitHub Sync — Feb 28, 2026" }
Schema Requirements
Every flagged item must have either task_link (Notion URL) or no_task_reason (explanation). The worker rejects invalid input.
Status Types:
sync - Continuous synchronization
snapshot - Point-in-time capture
report - Analysis or summary
heartbeat - Health check with no items
Status Values:
complete - Full success
partial - Some items processed
failed - Critical failure
full_report - Comprehensive analysis
stub - Placeholder run
Target Databases:
docs - Most agents write here
home_docs - Personal Ops Manager, Home & Life Watcher
Worker 2: check-upstream-status
Checks whether an upstream agent’s most recent digest is fresh and successful.
Example: Check Multiple Upstream Agents
const upstreamAgents = [
"Time Log Auditor" ,
"Docs Librarian" ,
"VEP Weekly Reporter" ,
];
for ( const agentName of upstreamAgents ) {
const result = await checkUpstreamStatus ({
agent_name: agentName ,
max_age_hours: 48 ,
require_current_cycle: true ,
});
if ( result . degraded ) {
console . log ( `⚠️ ${ agentName } is degraded: ${ result . data_completeness_notice } ` );
// Include data_completeness_notice in your digest
} else {
console . log ( `✅ ${ agentName } is current ( ${ result . status } )` );
}
}
Response Structure
{
success : true ,
agent_name : "Docs Librarian" ,
status : "complete" ,
run_time : "2026-03-02T14:30:00-06:00" ,
page_url : "https://notion.so/docs-quick-scan-mar-2" ,
degraded : false ,
data_completeness_notice : null
}
Degraded Response Example:
{
success : true ,
agent_name : "VEP Weekly Reporter" ,
status : "failed" ,
run_time : "2026-02-24T09:00:00-06:00" ,
page_url : "https://notion.so/vep-weekly-feb-24" ,
degraded : true ,
data_completeness_notice : "⚠️ VEP Weekly Reporter last ran 8 days ago (status: failed). Data may be incomplete."
}
Call check-upstream-status at run start
Query each upstream agent your agent depends on.
Check the degraded flag
If degraded: true, include data_completeness_notice in your digest’s summary or Data Quality section.
Proceed with your run
Use the upstream status to decide whether to proceed normally or mark your own run as degraded.
Worker 3: create-handoff-marker
Creates a handoff record when escalating to another agent. Enforces circuit breakers and escalation caps.
Example: Create Handoff with Task
const handoffInput = {
source_agent: "GitHub Insyncerator" ,
target_agent: "Client Repo Auditor" ,
escalation_reason: "Stale spike in CI failures; needs client repo audit" ,
source_digest_url: "https://www.notion.so/github-sync-2026-02-28-abc123" ,
create_task: true ,
task_priority: "🟡 Medium" ,
client_relation_ids: [],
project_relation_ids: [],
};
const result = await createHandoffMarker ( handoffInput );
if ( result . success ) {
// Paste result.handoff_block into your digest's Escalations section
console . log ( result . handoff_block );
if ( result . duplicate_prevented ) {
console . log ( `⚠️ Duplicate handoff prevented. Existing task: ${ result . existing_task_url } ` );
}
if ( result . escalation_capped ) {
console . log ( `⚠️ Escalation cap reached. Move to Needs Manual Review.` );
}
}
Response Structure
{
success : true ,
handoff_block : "- **Escalated to:** Client Repo Auditor \n - **Reason:** Stale spike in CI failures \n - **Task:** [View Task](https://notion.so/task-xyz) \n - **Owner:** Client Repo Auditor" ,
task_url : "https://notion.so/task-xyz" ,
duplicate_prevented : false ,
existing_task_url : null ,
escalation_capped : false ,
needs_manual_review : false
}
Circuit Breaker Rules
No duplicate handoff within 7 days for the same source→target pair. If a recent handoff exists, duplicate_prevented: true and existing_task_url is returned.
Escalation cap: Maximum 2 escalations in the same direction within 7 days. When exceeded, escalation_capped: true and needs_manual_review: true. Move the item to your digest’s “Needs Manual Review” section.
Task Priority Options
Complete Agent Workflow
Here’s how a typical agent uses all three workers:
Check upstream dependencies
const upstreamStatus = await checkUpstreamStatus ({
agent_name: "Time Log Auditor" ,
max_age_hours: 48 ,
require_current_cycle: true ,
});
const dataQualityNotice = upstreamStatus . degraded
? upstreamStatus . data_completeness_notice
: null ;
Perform your agent's work
// Your agent logic here
const flaggedItems = processTasks ();
const actionsTaken = createOrUpdateTasks ();
Create handoffs if needed
const handoff = await createHandoffMarker ({
source_agent: "Your Agent" ,
target_agent: "Target Agent" ,
escalation_reason: "Reason for escalation" ,
source_digest_url: "https://notion.so/your-digest" ,
create_task: true ,
task_priority: "🟡 Medium" ,
client_relation_ids: [],
project_relation_ids: [],
});
const escalations = [{
escalated_to: "Target Agent" ,
escalation_reason: "Reason" ,
escalation_owner: "Target Agent" ,
handoff_complete: false ,
}];
Write your digest
const digest = await writeAgentDigest ({
agent_name: "Your Agent" ,
agent_emoji: "🤖" ,
status_type: "sync" ,
status_value: "complete" ,
run_time_chicago: new Date (). toISOString (),
scope: "All items in scope" ,
input_versions: dataQualityNotice || "None" ,
flagged_items ,
actions_taken ,
summary: "Run summary" ,
needs_review: [],
escalations ,
target_database: "docs" ,
doc_type: "Agent Digest" ,
client_relation_ids: [],
project_relation_ids: [],
});
console . log ( `✅ Digest created: ${ digest . page_url } ` );
Run Tests
Verify everything works:
All tests
Watch mode
Integration tests
Coverage
1Password
Integration tests require TEST_NOTION_TOKEN and TEST_DOCS_DATABASE_ID in your environment. Always use a dedicated test database, never production.
Deploy to Production
Build and deploy with the ntn CLI:
Or use the combined script:
Next Steps
API Reference Detailed schemas and return types for all three workers
Governance Docs Read WORKERS.md, AGENTS.md, ARCHITECTURE.md, and GUARDRAILS.md in the repository