Free for 30 days on Scale.Start free
Vendor contract renewal tracker
Every step in the template

Vendor contract renewal tracker

A rolling daily workspace where every vendor contract has one row, the agent surfaces upcoming renewals at 90 / 60 / 30 days out with a tailored recommendation, and you never get caught flat-footed by an auto-renew that fired without notice.

Outcome

A rolling daily workspace where every vendor contract has one row, the agent surfaces upcoming renewals at 90 / 60 / 30 days out with a tailored recommendation, and you never get caught flat-footed by an auto-renew that fired without notice.

Time1 hour first-time setup, ongoing ~5 min/day reviewDifficultybeginnerForOps + finance leads at PE-backed mid-market companies managing a vendor portfolio.
How this works

Open it, hand it to your agent, walk the steps.

Paste this to your agent (Claude / Cursor / Codex)
You are the agent running on the "Vendor contract renewal tracker" template workspace, connected via MCP at your-org/vendor-contract-renewal-tracker.

Your job: surface every vendor contract that's hitting a 90 / 60 / 30 day renewal window, draft a renew-or-renegotiate recommendation per contract, log to Renewal alerts + Status. Never modify contract terms.

User-loop protocol:
- You propose. The owner decides. Never change Contracts.status, Contracts.annual_value, Contracts.auto_renew, or Contracts.owner.
- Daily 9 AM (or "scan renewals"): read all Contracts rows. For each row with a Renewal Date in YYYY-MM-DD, compute days until renewal. For each unticked 90 / 60 / 30 day window the contract is now inside, draft a recommendation and post an alert.
- Recommendation must cover: (1) renew vs renegotiate vs competitive bid; (2) the risk if no action is taken before the notice period lapses; (3) one specific next step for the owner. 3-5 sentences. No filler, no hedging.
- Post the recommendation as a new entry at the top of Renewal alerts doc, prefixed with a timestamp and the contract vendor. Tick the "Alert Sent (90d)" / "(60d)" / "(30d)" column on the Contracts row so the same window doesn't fire twice.
- If SLACK_WEBHOOK_URL is set, post a Slack alert with the vendor, renewal date, annual value, and recommendation.
- End of every working session, write 1 paragraph to Status: how many contracts scanned, how many alerts sent, the next renewal due.

Don't touch:
- Contracts.status (Active / Cancelled / Renewed / Under Review is the operator's tag).
- Contracts.annual_value / .notice_period_days (those are the operator's source of truth from the original contract).
- Renewal alerts entries older than 30 days (those are history).

First MCP tool calls:
1. list_surfaces(workspace_slug="vendor-contract-renewal-tracker")
2. list_rows(workspace_slug="vendor-contract-renewal-tracker", surface_slug="contracts")
3. get_doc(workspace_slug="vendor-contract-renewal-tracker", surface_slug="status")
The template · 5 steps

Top to bottom. Each step has tasks, pointers, gotchas.

Seed Contracts with every vendor relationship

30-60 min for a first sweep

Populate the Contracts table with one row per vendor contract you currently have running. The minimum required fields are Vendor, Renewal Date (YYYY-MM-DD), Annual Value, and Owner. The richer the Notes, the better the agent's recommendation. Auto-Renew, Notice Period (Days), Category, and Status columns are pre-created and fillable as you learn each contract's terms.

Tasks
  • List every vendor relationship (software, facilities, professional services, logistics)
  • For each: pull the latest signed contract, find the renewal date + notice period
  • Create Contracts rows: Vendor, Category, Annual Value, Renewal Date (YYYY-MM-DD), Owner, Auto-Renew (Yes/No/Unknown), Notice Period (Days), Notes, Status (Active by default)
  • If you don't have the contract in hand, mark Status as Under Review and add to Notes what you need
Gotchas
  • Renewal Date must be ISO YYYY-MM-DD. Anything else and the agent skips the row.
  • Annual Value is the operator's number. If the contract has tiered pricing, use the current tier; don't average.
  • Auto-Renew = Unknown is fine. The agent surfaces the contract earlier (90 days) when Auto-Renew is Yes or Unknown.

Install the daily renewal-check script

15 min

The agent's daily routine is a Python script that reads Contracts via the Dock REST API, computes days-to-renewal per row, drafts the recommendation via the Anthropic API, posts to Slack (optional), and ticks the row's alert columns. Install it locally or in your cron host.

Tasks
  • Open Setup guide (doc) and copy check_renewals.py into a local folder
  • Run pip install anthropic requests python-dotenv
  • Create a .env with DOCK_API_KEY, DOCK_WORKSPACE_SLUG, ANTHROPIC_API_KEY, SLACK_WEBHOOK_URL (optional), ALERT_WINDOWS=90,60,30, CURRENCY_SYMBOL=$, CLAUDE_MODEL=claude-sonnet-4-6
  • Generate a Dock API key at trydock.ai/settings/api
  • Run python check_renewals.py once manually. Watch Renewal alerts + Status for the first entries
Gotchas
  • DOCK_WORKSPACE_SLUG must match the workspace you forked this template into. If you renamed the workspace, update the env var.
  • If a 90-day alert fires for a contract that was just renewed but the row wasn't updated, the agent will alert again at 60 days. Update Status=Renewed when the renewal is confirmed and the agent will skip past windows.

Schedule the daily run

10 min

Pick one of two paths to run the script every morning. Cron is simplest if you have an always-on Mac or Linux box. CueAPI is the right pick if you want cloud-scheduled execution that survives your laptop closing.

Tasks
  • Option A — cron: crontab -e, add `0 9 * * * cd /path/to/script && source .env && python3 check_renewals.py >> renewal_check.log 2>&1`
  • Option B — CueAPI: pip install cueapi cueapi-worker, then cueapi create --name vendor-contract-renewal-check --schedule '0 9 * * *' --handler ./check_renewals.py
  • Either way: confirm the next morning that Status has a fresh session entry
Gotchas
  • Cron requires the machine awake at 9 AM. If you close your laptop overnight, switch to CueAPI.
  • CueAPI worker must be running for cues to fire. Run cueapi-worker start once + supervise it with launchd / systemd.
Agent prompt for this step
Run a first scan of the Contracts table. For every row with a Renewal Date set, compute days until renewal. For any row inside a 90 / 60 / 30 day window that hasn't been alerted yet (the "Alert Sent (Xd)" column is blank), draft a recommendation (renew / renegotiate / bid) and append to Renewal alerts. Tick the alert column. Post a Status entry summarizing: rows scanned, alerts sent, next renewal due.

Wire the optional Slack alert

5 min

If your contract owners live in Slack, post each recommendation there. Create one incoming webhook for the ops or finance channel, paste it into SLACK_WEBHOOK_URL. The script already builds a clean Block Kit message: header with urgency emoji (90 yellow, 60 orange, 30 red), section with contract details, recommendation, and a back-link to the Dock workspace.

Tasks
  • Create an incoming webhook at api.slack.com/apps → New App → From scratch → Incoming Webhooks → Add to channel
  • Paste the webhook URL into SLACK_WEBHOOK_URL in .env
  • Manually trigger a scan to verify the message lands in the right channel

Set the renewal-decision review cadence

15 min/week ongoing

The agent surfaces; the owner decides. Pick a weekly time to review Renewal alerts (Friday 4 PM is the operator default), make the renew / renegotiate / bid call, update Contracts.status accordingly, and message the vendor before the notice period lapses.

Tasks
  • Block 15 min on the calendar weekly (Friday 4 PM default)
  • Open Renewal alerts (doc). Walk through every alert since last review
  • For each: confirm or override the agent's recommendation, update Contracts.status (Active / Renewed / Under Review / Cancelled)
  • Message the vendor with renewal / renegotiation / bid intent
Gotchas
  • If you don't act on a 30-day alert and the contract has auto-renew, you will renew at the existing terms. Default Contracts.status=Renewed only after you've explicitly confirmed terms.
FAQ

Common questions on this template.

How does this know which contracts are coming up?
A daily Python script reads the Contracts table from this Dock workspace, computes days until each row's Renewal Date, and fires an alert the first time a contract enters the 90 / 60 / 30 day window. Each alert is tracked on the row itself so the same window doesn't fire twice.
Does the agent renew or cancel contracts on my behalf?
No. The agent surfaces upcoming renewals and drafts a recommendation for each. You decide and message the vendor. The agent doesn't touch Contracts.status, Annual Value, or Auto-Renew — those are operator-only fields.
What if I don't have Slack?
Skip the SLACK_WEBHOOK_URL env var. The agent still appends every alert to the Renewal alerts doc surface and the Status doc surface inside Dock. You'll see them when you open the workspace.
Can I change the alert windows?
Yes. Set ALERT_WINDOWS in .env to a comma-separated list of day counts. The default is 90,60,30. If you only want one alert, set it to 60. If you want earlier visibility for high-value contracts, set 120,90,60,30. The script and the agent both read this value.
Does this work with Salesforce / HubSpot for contract data?
Not in v1 — Contracts is the canonical source. The script reads from the Dock table. A future extension can pull contract metadata from a connected CRM or CLM (Ironclad, ContractWorks, Spotdraft) on a daily sync and write to Contracts.

Open this template as a workspace.

We mint a fresh copy in your org with the steps as table rows, the pointers as a separate table, and the brief as a doc. Bring your agents, start checking off boxes.