Alfred
Reads Canvas assignments via the API and iCal feed.
Reads GitHub notifications and allows approval-gated creation of issues.
Reads unread Gmail message headers and snippets, with approval-gated draft and send capabilities, plus inbound email command processing.
Reads selected Google Calendar events and supports approval-gated event creation.
Maintains a two-way sync with an Obsidian vault for typed temporal memory.
Interfaces with Slack via Socket Mode for paired channels, supporting replies, reminders, and briefs.
Interfaces with Telegram for messaging, reminders, and briefs to explicitly paired chats.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@AlfredWhat does my day look like tomorrow?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Alfred
Alfred is a local-first, open-source personal secretary that runs on your PC. It remembers what you tell it, keeps a typed temporal memory graph with evidence-backed provenance, briefs you from Calendar, Gmail, Canvas, and GitHub, and acts on your behalf—creating events, drafting and sending mail, filing issues—only after you preview and approve. SQLite owns memory, tasks, schedules, audit records, and connector state. Telegram, Slack, Claude, Cursor, ChatGPT, and the CLI are replaceable interfaces, not the source of truth.
Credentials stay in the OS credential store. Tokens never land in the database, audit log, Markdown vault, or Git. Writes are preview-then-confirm. Models are optional and off the default path.
What you get
A local SQLite archive with an append-only audit log and encrypted backup
Typed temporal memory (search, correct, forget) and a two-way Obsidian vault
Read-only Calendar / Gmail / Canvas / GitHub / Health sync feeding a morning brief
Approval-gated writes: Calendar events, Gmail drafts and sends, GitHub issues
Telegram (and optional Slack) as the phone remote; Claude, Cursor, and ChatGPT over policy-gated MCP
alfred runor a Windows service that keeps the loop alive
See ARCHITECTURE.md for the decisions behind this. Commands and setup are below.
Local setup
python -m venv .venv
.\.venv\Scripts\python -m pip install -e .[dev]
.\.venv\Scripts\alfred init
.\.venv\Scripts\alfred statusOr run those four steps with .\scripts\install.ps1. It is safe to re-run: it
skips venv creation when one already exists, never reads or requests a
provider credential, and every mutating step honors -WhatIf. Add
-RegisterScheduledTask to also register the Task Scheduler entry in
"Running continuously"; Get-Help .\scripts\install.ps1 -Full lists every
parameter.
The default database is .alfred/alfred.db, which Git ignores. Use another
path with --db <path> or ALFRED_DB_PATH.
Optional quiet hours hold proactive Telegram/Slack deliveries (reminders,
morning briefs, nags—anything with an outbox job_id) inside a local window.
Set ALFRED_QUIET_HOURS_START and ALFRED_QUIET_HOURS_END to HH:MM
(overnight windows like 22:00–07:00 are fine) and optionally
ALFRED_QUIET_HOURS_TIMEZONE to an IANA name (default UTC). Interactive
replies with no job_id still deliver. Unset means quiet hours are off.
Related MCP server: razberri MCP Server
Local connectors
Store every token under OS credential-manager service alfred. Alfred never
writes credentials to its database, audit log, vault, or Git.
Approval-gated writes (Calendar events, Gmail drafts and sends, GitHub issues, memory forget, backup restore) are always three steps:
*-propose— local preview; never touches the provider.alfred approval-approve --approval-id <ID> --actor nico— prints a one-time token.*-execute --approval-id <ID> --actor nico --token <TOKEN>— consumes that token.
Retrying the same approval ID and token replays the stored receipt instead of
duplicating. If the PC fails after the provider accepts but before Alfred
records the receipt, the same command recovers via a stable provider ID and
fails closed on an absent or ambiguous result. There is no MCP tool to
approve: a human (or a trusted local channel outside the MCP client, e.g.
alfred approval-approve) has to grant it.
Connector | Credential (account) | Read | Write |
Telegram |
| paired chats | replies, reminders, briefs |
Slack |
| Socket Mode, paired only | same |
Google Calendar | OAuth via | selected calendars | approval-gated event create |
Gmail | same OAuth grant | unread headers/snippets | approval-gated draft and send |
Canvas API |
| assignments | — |
Canvas iCal |
| dated assignments | — |
GitHub |
| unread notifications | approval-gated issues |
Google Health | extra OAuth scopes | sleep, activity, metrics | — |
Composio |
| overflow apps (Notion, Spotify, …) | approval-gated writes |
Slack is built and unit-tested against synthetic fixtures but has not
been exercised against a real Slack app. Google Health's list client now
matches the published v4 shapes (typed filters, nested payloads, empty
name on non-identifiable points, sleep page size 25); it still keeps the
complete raw point in metadata["raw"] and still needs a live wearable-
linked grant (alfred google-auth --include-health) before treating the
connector as verified.
alfred connector-status (or MCP connector_status) reports ok, stale
(no success in 24 hours), error, or never_synced without exposing a
credential or synced content.
alfred connector-capabilities answers what each connector is allowed to
do: who can write, which OAuth scopes are actually requested, which stores
sensitive data, and whether it polls, pushes, or is local. Today six can
write (Calendar, Gmail, GitHub, Telegram, Slack, Composio) and exactly one stores
sensitive data (Google Health, all three scopes read-only). "Can write"
marks the approval boundary—nothing there runs unattended. The same table is
on the admin dashboard and is cross-checked against the source by tests.
Telegram and Slack
Put the bot token under telegram-bot-token, then run alfred telegram-poll
with explicitly paired chat/user IDs. Only those pairs enter Alfred.
Slack stays local through Socket Mode—no public webhook or tunnel.
deploy/slack-app/manifest.yml is a ready-to-paste Slack app;
deploy/slack-app/README.md covers generating tokens, storing them as
slack-app-token/slack-bot-token, inviting the bot, and finding IDs. Then
add --slack-pair CHANNEL_ID:USER_ID --slack-channel-id CHANNEL_ID to
alfred run. Only paired user/channel combinations enter Alfred; replies,
reminders, and briefs can only go to explicitly allowed channels.
Google OAuth (Calendar, Gmail, Health)
Calendar and Gmail share one OAuth 2.0 flow. In Google Cloud Console, create
an OAuth client of type "Desktop app" (no redirect URI—Alfred's local
loopback flow is exempt) and save its client ID and secret as
google-oauth-client-id and google-oauth-client-secret. alfred google-auth
opens a browser, receives the redirect on a local port, and stores a refresh
token as google-oauth-refresh-token. Later syncs mint a fresh access token
from that refresh token; none is cached. Re-run google-auth if the grant is
revoked.
The always-on runner reads every calendar selected in the Google Calendar UI:
title, timing, status, and a source link—never event descriptions or attendee
lists. Each event also keeps its calendar ID/name and Google's read-only
creator/organizer identity when available, so Alfred can say where an event
came from without copying the guest list. That needs the narrow
calendar.calendarlist.readonly scope in addition to event access. A one-shot
alfred calendar-sync can still target one calendar explicitly.
Calendar writes: alfred calendar-event-propose --actor nico --summary "..." --start <ISO-8601> --end <ISO-8601>, then approve, then
alfred calendar-event-execute. Recovery uses Alfred's stable Calendar event
ID.
Gmail reuses the same grant. alfred gmail-sync copies each unread message's
subject, sender, and Gmail's short snippet—never the body or attachments.
Reading or archiving a message drops it from the next sync. Sync is bounded
to the most recent --limit unread messages (default 500, Gmail's
newest-first order) rather than the whole backlog. A message can drop out
because it was read/archived or because it fell outside that window—both
look the same in connector-status.
Gmail drafts and sending are separate approval-gated writes:
gmail-draft-propose / gmail-draft-execute creates a draft and never calls
a send endpoint. To send, use gmail-send-propose with the same recipient,
subject, and body, approve separately, then gmail-send-execute. Alfred never
sends from a sync, scheduled job, or a proposal alone. Recovery uses a stable
Message-ID and only accepts an exact match.
Alfred can also take commands from your inbox. alfred gmail-inbound-poll --sender you@example.com turns a subject of Task: <title> into a local
task, or Remind: <ISO-8601 time> <title> into a task with that due date.
Only mail from an explicitly listed --sender is acted on; ordinary mail is
left untouched. A recognized command from a sender who is not listed is
rejected and audited (the same default-deny rule Telegram pairing uses). Add
--destination telegram:123 to also deliver Remind: reminders there.
Alfred never replies by email from this path. Pass --gmail-inbound-sender
(and optionally --gmail-inbound-destination) to alfred run to poll
continuously.
Google Health reuses the same grant but needs extra scopes Calendar/Gmail do
not request by default. Enable the Google Health API on the Cloud project,
add the three googlehealth.*.readonly scopes on the OAuth Data Access
page, then:
alfred google-auth --include-healthThat keeps every Calendar/Gmail default (including
calendar.calendarlist.readonly) and adds sleep, activity, and vitals
read-only. Health is never implied by a plain google-auth. Google Health
rejects access tokens that also carry Calendar/Gmail scopes, so
alfred health-sync refreshes a health-only subset of that grant. The
Google account must also be linked to Fitbit (Google Health returns
ACCOUNT_NOT_LINKED until it is). It copies the last 14 days (--lookback-days to change that) of steps, sleep
sessions, and daily resting heart rate as sensitive-tagged events—health
metrics never inherit personal's default retrieval scope. Sample-level
BPM is not stored; it is too dense for the event log. Health writes stay
disabled.
Canvas
If your school permits a personal Canvas token, save it as canvas-api-token
and run alfred canvas-sync --base-url https://your-school.instructure.com.
It copies upcoming/missing plus accessible current/completed-course assignment
history: title, deadline, course label, source link, and compact submission
workflow state. Grades, submission contents, files, and assignment body text
stay out.
If the school disables personal API tokens, use Canvas's private Calendar Feed. Treat that URL like a password and enter it in Windows Credential Manager; never put it in Git, a command argument, a log, or chat:
.\.venv\Scripts\alfred.exe canvas-ical-setupThe setup command says when it is ready for the URL, hides the pasted text,
repairs an exact accidental double-paste, validates the feed before replacing
the saved credential, and performs the first sync. With --canvas-ical,
alfred run checks the feed every 15 minutes, uses ETag/Last-Modified
conditional requests, and stores only assignment title, deadline, course
label when present, a query-free source link, status, and versioned evidence.
It never stores the feed URL or event description.
If the same item also arrives through a Google Calendar subscription, exact matches on title and time are shown once in briefs and academic memory, with native Canvas evidence preferred. Canvas's iCal export is less complete than the API: it omits To Do/submission state and is limited by Canvas to 30 past days, 366 future days, and 1,000 items. Remove the same Canvas subscription from Google Calendar later if you do not want the redundant raw calendar evidence; it is no longer required to prevent duplicate briefing or memory entries.
GitHub
GitHub's notifications endpoint needs a classic personal access token with
the notifications scope; save it as github-token, then run
alfred github-sync. It copies only each unread notification's title,
repository, reason (mention, review requested, etc.), subject type, and a
browser deep link—never issue/PR body text or comments. Resolved or read
notifications drop out of the next sync automatically.
Issue creation is a separate write scope. A fine-grained token needs
Issues: write on only the repository you choose; save it as
github-issue-token. alfred github-issue-propose --actor nico --repository owner/repo --title "..." creates a local preview; after approve,
github-issue-execute creates that exact issue once. It never creates issues
during sync or without a fresh approval token. Each created issue includes an
invisible Alfred recovery marker so a crash between GitHub accepting it and
Alfred storing the receipt can still find that exact issue. PR comments use
the same recovery process.
Composio (overflow apps)
Use this for apps Alfred does not already own — Notion, Spotify, Linear, Discord, and the rest of Composio's catalog. Gmail, Calendar, GitHub, Slack, Telegram, and Fitbit stay first-party.
Create a free project at dashboard.composio.dev (no card; new signups are hard-capped at 100k tool calls/month).
Copy an API key from Settings and run
alfred composio-setup.alfred composio-connect notionprints a Connect Link; open it, sign in, thenalfred composio-search "list pages" --toolkit notion.Grant Hermes the four tools (
composio_search,composio_status,composio_connect,composio_execute) on the existingclient-grant.
Reads run immediately. Writes still preview and wait for the Telegram approve button. Do not add Composio's hosted MCP URL to Hermes — every Telegram turn runs YOLO, so that path would auto-approve third-party writes.
alfred composio-status shows connected accounts and this UTC month's local
call count against the free-tier cap.
Morning brief
Queue a daily local morning brief for a paired Telegram chat with, for
example, alfred schedule-brief --chat-id 123 --at 07:30 --timezone America/New_York.
Encrypted backup and restore
Create the local AES-256 key once with alfred backup-key-generate; it is
kept only in Windows Credential Manager as backup-encryption-key. Then
alfred backup-create --output D:\Backups\alfred.backup writes an encrypted
SQLite snapshot. Restore is two-step: backup-restore-propose --backup ... --actor nico, approve the preview, then backup-restore-execute. The
backup's SHA-256 is frozen in the approval, so a changed file cannot be
restored with a stale confirmation. Restore is non-replayable: any further
restore needs a new preview and approval.
scripts/backup.ps1 creates timestamped encrypted snapshots under
.alfred/backups. The deployed installation runs it through the Alfred Backup scheduled task daily at 02:30.
Test those snapshots with alfred backup-verify --latest-in .alfred\backups
(or --backup <file>). It rehearses a full restore into a throwaway copy and
never touches your live database. The only other way to test a restore is
backup-restore-execute, which overwrites the database you are trying to
protect.
It checks that the stored key still decrypts, SQLite integrity passes, migrations apply, the audit hash chain verifies, and the data is really there:
{"ok": true, "schema_version": 15, "audit_chain_verified": true,
"row_counts": {"events": 3402, "tool_runs": 5369, "memories": 2592}}A backup that decrypts into an empty database would pass every check except that last one. Broken backups are reported rather than raised—so this is safe to schedule—and the command exits non-zero on failure.
scripts/verify-backup.ps1 is the scheduled wrapper. The deployed
installation runs it as Alfred Backup Verify every four weeks at 03:15—45
minutes after the nightly snapshot. Each run appends a JSON line to
.alfred\backup-verify.log, and a failure throws so Task Scheduler records a
failed run. Register it with:
$ps = (Get-Command powershell.exe).Source
$action = New-ScheduledTaskAction -Execute $ps `
-Argument '-NoProfile -ExecutionPolicy Bypass -File "C:\path\to\alfred\scripts\verify-backup.ps1"'
$trigger = New-ScheduledTaskTrigger -Weekly -WeeksInterval 4 -DaysOfWeek Sunday -At 3:15AM
Register-ScheduledTask -TaskName "Alfred Backup Verify" -Action $action -Trigger $trigger -ForceTasks and reminders
Sending /task <title> or /remind <ISO-8601> <text> to the paired Telegram
bot creates a task (and, for /remind, a scheduled delivery job) linked back
to that message as evidence. The same commands exist on the CLI:
alfred task-upsert "title" [--task-id ID] [--due-at ISO-8601]— create, or update title/due date when--task-idis given. Omitting--due-aton an update leaves the existing due date alone rather than clearing it.alfred task-complete --task-id ID— idempotent; completing an already-completed task is a no-op.alfred reminder-set "text" --run-at ISO-8601 --chat-id ID [--task-id ID]— schedules a Telegram reminder, creating its own task if--task-idisn't given. New channels use--destination channel:recipient(for exampleslack:D123); the durable job and outbox preserve that target rather than silently routing it to Telegram. Delivery workers still only exist for Telegram today.
All three are also MCP tools (task_upsert, task_complete, reminder_set).
reminder_set needs an explicit chat_id because Telegram is Alfred's only
delivery channel today.
Running continuously
Every command above is a one-shot CLI invocation. alfred run is the
always-on process: each cycle handles Telegram intake/delivery and any due
jobs (reminders, the morning brief), and each configured connector syncs on
its own interval (15 minutes by default). A missing credential or a failed
connector is logged to the audit trail and skipped; it never stops the loop
or any other connector.
.\.venv\Scripts\alfred run --pair 123:456 --chat-id 123 --canvas-icalalfred run bounds Gmail to the 50 most recent unread messages
(--gmail-unread-limit), lower than one-shot gmail-sync's 500. Each sync
blocks this single-threaded loop; against a real account 500 measured at 45
seconds versus 7 for 50, which is dead time where an incoming Telegram
message isn't even polled. Raise it if you'd rather have the wider window
than the responsiveness.
Calendar, GitHub, and Gmail sync are always attempted and skip themselves if
their credential isn't configured yet. Canvas API sync needs
--canvas-base-url, native Canvas Calendar Feed sync needs --canvas-ical,
inbound Gmail commands need at least one --gmail-inbound-sender, and Google
Health needs --google-health. Omit --pair/--chat-id to run with
Telegram disabled. Stop it with Ctrl+C.
alfred run also works as a foreground process kept alive by Windows Task
Scheduler ("At log on", running pythonw.exe against this same command) or a
terminal left open. .\scripts\install.ps1 -RegisterScheduledTask -RunArgs "--pair 123:456 --chat-id 123" registers that entry; inspect it with
Get-ScheduledTask -TaskName Alfred and remove it with
Unregister-ScheduledTask -TaskName Alfred. Either way, Alfred only runs
while someone is logged in.
Conversational replies (--hermes-profile)
By default a Telegram message that isn't /task or /remind gets a short
help receipt. Add --hermes-profile alfred and it goes to the agent: Hermes
understands it, calls Alfred's MCP tools, and answers in the same chat.
.\.venv\Scripts\alfred run --pair 123:456 --chat-id 123 --hermes-profile alfredInstall hermes-profile/ and register its MCP connection first (see
hermes-profile/README.md). Alfred owns the Telegram transport; Hermes is a
one-shot subprocess (hermes -p <profile> -z <message>) and never touches
Telegram itself—Hermes's own Telegram gateway does not currently work on this
platform. Production stays on that bounded, redacted one-shot runner: Hermes
ACP/serve fix the tool surface at session start, while Alfred narrows MCP
tools per turn, and a fresh zero-tool ACP session exceeded 30 seconds before
a prompt ran.
Work turns get a keyword acknowledgement first (
checking your agenda...,drafting email to you@example.com...); casual turns skip it. Acknowledgements are not model calls—they're produced inside the intake write transaction, and the agent turn has to wait until that transaction closes.Telegram
typing...is best effort and never blocks the durable answer.Answers arrive as two to four consecutive messages (
SOUL.mdasks for short paragraphs; the bridge sends each as its own message).Inbox/GitHub questions get a bounded context pack from already-synced local records before Hermes starts. Promotions, Social, and Forums are counted but omitted by default. Gmail context is still headers/snippets only. Synced message content remains untrusted data.
Work turns include two recent completed exchanges so
yes, flag thatkeeps its referent. Casual turns use up to eight exchanges from the last week,poolside/laguna-xs-2.1:freewith reasoning disabled, FTS-only memory, and an empty MCP tool surface (no Ollama embedding wait on greetings). Tool-backed and explicit memory questions keep hybrid vector recall andstepfun/step-3.7-flash:free. Override the casual model with--hermes-conversation-model.Every Hermes turn independently allowlists at most eight MCP tools.
alfred-mcpregisters only that list; an inbox/GitHub read already in the pack exposes no tools. This does not narrow Claude, Cursor, HTTP, or other MCP clients.--hermes-command(defaulthermes; full path when PATH differs under the Windows service),--hermes-timeout(default 120s; timeout/nonzero/empty still gets one honest reply, never retried),--hermes-pythonto invoke-m hermes_cli.maininstead of the console launcher,--embedding-model nomic-embed-textfor hybrid recall,--hermes-monthly-call-limit(hard cap, default 1000). On Windows, children useCREATE_NO_WINDOW.Bridge context is bounded before launch; common PII is redacted at the subprocess boundary. The shipped profile uses Nous free tier plus local Ollama fallback; no paid provider fallback.
alfred latency-status --limit 20 reports content-free p50/p95 timing
(acknowledgement, context assembly, Hermes call, response-ready, first
delivered reply). Samples contain only an update ID, runtime/tool count,
outcome, and timings. Telegram timestamps have one-second resolution, so
treat end-to-end totals as operator-facing, not a microbenchmark.
For inbox/GitHub questions, the bridge assembles a bounded context pack from
the already-synced local records before starting Hermes. That avoids a second
MCP discovery/tool-call loop on the cold path. Gmail's Promotions, Social,
and Forums categories are counted but omitted from the pack by default, and
two recent completed chat exchanges are included for work turns so a precise
follow-up such as yes, flag that keeps its referent. Casual turns use up to
eight completed exchanges from the last week, poolside/laguna-xs-2.1:free
with reasoning disabled, exact local FTS memory recall, and an empty Alfred
MCP tool surface. Skipping the optional vector lookup avoids waiting for an
Ollama embedding on greetings; tool-backed and explicit memory questions keep
hybrid vector recall and the profile's stronger stepfun/step-3.7-flash:free
default. Override the casual model with --hermes-conversation-model. Synced
message content remains untrusted data, and Gmail context is still
headers/snippets only, never a full message body.
The bridge also narrows Alfred's MCP surface independently for every Hermes
turn. A deterministic classifier uses the current request plus the two recent
exchanges to select at most eight task, calendar, communication, memory, or
status tools. alfred-mcp registers only that allowlist in the child process;
an inbox/GitHub read already satisfied by the context pack exposes no tools.
This is defense in depth on top of the existing per-client policy checks and
does not narrow Claude, Cursor, HTTP, or other MCP clients.
alfred latency-status --limit 20 reports content-free p50/p95 timing for the
Telegram acknowledgement, local context assembly, Hermes call, response-ready
point, and first delivered reply. Recent samples contain only an update ID,
runtime/tool count, outcome, and timings; message and connector content never
enters the report. Telegram's source timestamp has one-second resolution, so
acknowledgement and delivered totals are best treated as operator-facing
end-to-end measurements rather than a microbenchmark.
alfred evaluation-status --window-days 30 closes the other half of that loop.
Alfred already recorded response feedback, memory retrieval outcomes, workflow
proposal decisions, and implicit-candidate promotion; this reads them back as
one summary instead of leaving four tables nobody queries. It also reports
which context sources were present when each feedback vote landed — a starting
point for "why was that answer wrong", not proof of cause, since a turn packs
several sources at once. The same summary is a page in the admin UI. Nothing
here runs a model, writes a row, or changes ranking, and the output is
content-free (outcomes, counts, source names, opaque record IDs), so it is
safe to paste into an issue. A metric with no votes yet reports null rather
than 0 — a system nobody has rated is not a system that scored zero.
Hermes ACP and serve were evaluated as ways to remove the one-shot process
start. ACP passes its compatibility check, but its tool surface is fixed when
a session is created, while Alfred narrows MCP tools for every turn. Creating
a fresh zero-tool session preserved that boundary but exceeded 30 seconds in
two bounded trials before a prompt even ran because Hermes constructs a fresh
agent per session. Reusing one session would be faster only by retaining an
unbounded hidden transcript and a fixed tool surface. Production therefore
stays on the bounded, redacted one-shot runner until upstream exposes a
per-prompt tool override or cheap isolated sessions; failures and timeouts
continue to produce one honest reply without retrying.
Persistent learning
When conversational replies are enabled, Alfred also runs a local learning
pass after the reply has already been delivered. Explicit remember that ...
statements become confirmed memories immediately. Ordinary preferences,
identity facts, and goals enter as quarantined candidates and need the same
fact in a separate source event before promotion. Sensitive candidates never
auto-promote, recognizable secrets are not stored, and every observation
keeps its immutable source-event provenance.
Confirmed memories relevant to a request are placed directly in the bridge's
bounded context pack, avoiding another agent tool round trip. Candidate,
superseded, rejected, deleted, sensitive, and secret memories are excluded
from that automatic path. memory_correct preserves the former version while
installing a correction; memory_feedback records relevant, irrelevant, or
incorrect retrievals as append-only evaluation data. That feedback now reorders
only the memories already selected for a matching query; it cannot inject an
unrelated popular memory into the candidate set.
Alfred grades its own answers instead of asking you to. Every successful reply
used to end with helpful, missing context, and wrong context buttons;
rating a secretary after each answer is work, so they went mostly unpressed,
and the correction was already in the chat anyway. Two detectors now produce
the same three verdicts. The first reads your next message for an unambiguous
reaction — "you missed the one from sam", "that's the wrong week", "thanks,
that's perfect" — using named rules rather than a model call, so it can be
read and argued with, and it stays silent on anything it does not clearly
recognize. The second is something you could not notice at all: when a reply
was built from a connector that has never synced or last synced a day ago, the
answer was already missing context, and that turn is flagged as it is stored.
Each verdict records a content-free trace of source names, connector freshness,
the name of the rule that fired, and opaque ranked record IDs; neither the
prompt nor the answer is stored. Helpful and wrong signals can reorder Gmail or
GitHub records only within their existing deterministic priority tier, while
missing context stays an evaluation signal instead of guessing what was
absent. A response holds one verdict per detector and still counts once in
ranking, inferred verdicts are attributed only to the paired sender's own
recent turn, and none of this can approve or execute an action. Buttons are now
reserved for exactly that: approving or cancelling a write.
alfred evaluation-status and the admin UI say how each verdict was reached, so
inferred signal is never mistaken for something you said. Answers Alfred flagged
against itself are counted separately from your verdicts and kept out of the
helpful rate — a connector going quiet is connector health, and folding it in
would make a week of stale Gmail read as a week of answers you disliked.
Calendar and Canvas history use a separate derived academic layer. Immutable connector events remain authoritative; after connector sync, Alfred deduplicates revisions into daily JSON rollups and course/calendar profiles, classifying exams, quizzes, assignments, and ordinary events while retaining each source-event ID. Academic questions retrieve only a few matching rollups (rather than scanning raw history), and rebuilding is skipped when the source fingerprint has not changed. A second deterministic pass promotes the current items into source-linked semantic memories, supersedes changed provider versions, and connects calendar/course entities to the owner graph. This background work never delays a chat reply.
The continuous runner refreshes a three-year Calendar window weekly by
default without replacing Calendar's live incremental cursor. Canvas keeps
the small upcoming/missing read on the normal connector interval and scans
accessible active/completed course assignments only once daily. Use
--calendar-history-days 0 to disable Calendar history, or tune
--calendar-history-interval and --canvas-history-interval when needed.
One-shot maintenance is available through calendar-history-sync --all-selected --days 1095 and academic-memory-rebuild.
The JSON in rollups is a replaceable cache, not the canonical archive. This
keeps exports portable while preserving edits, cancellations, provenance, and
forget/correction behavior in SQLite. Cognee is therefore not a source of
truth for Alfred today: its graph/vector retrieval ideas are useful, but its
LLM-backed ingestion and additional runtime/database surface are unnecessary
for deterministic Calendar/Canvas facts. It can be evaluated later as an
optional retrieval backend against the same source-linked memory tests.
alfred evaluation-status --window-days 30 summarizes response feedback,
memory retrieval outcomes, workflow proposal decisions, and
implicit-candidate promotion—plus which context sources were present when
each vote landed (a starting point for "why was that answer wrong", not
proof of cause). Same page in the admin UI. Nothing here runs a model,
writes a row, or changes ranking. Output is content-free (outcomes, counts,
source names, opaque IDs), safe to paste into an issue. A metric with no
votes yet reports null, not 0.
The agent step runs between intake and delivery, not as a connector. When a chat transport is configured, periodic connectors run sequentially on one bounded background worker, so a long Calendar/Gmail/Canvas batch cannot stop Telegram from polling. Telegram's server long-poll is ten seconds by default; the HTTP read budget is only two seconds longer, and a failed poll retries after one second.
Persistent learning
After a conversational reply is delivered, Alfred runs a local learning pass:
Explicit
remember that ...becomes a confirmed memory immediately.Preferences, identity facts, and goals enter as quarantined candidates and need the same fact in a separate source event before promotion.
Sensitive candidates never auto-promote; recognizable secrets are not stored; every observation keeps immutable source-event provenance.
Confirmed memories relevant to a request go in the context pack. Candidate, superseded, rejected, deleted, sensitive, and secret memories do not.
memory_correctpreserves the former version.memory_feedbackrecords relevant/irrelevant/incorrect retrievals as append-only evaluation data and reorders only memories already selected for a matching query.
Telegram no longer puts helpful / missing context / wrong context
buttons on every reply. response_context is still stored; a later pass
should infer those labels from the following conversation instead of asking
the owner to tap them. Existing votes still reorder Gmail or GitHub records
only within their deterministic priority tier.
Calendar and Canvas history use a derived academic layer. Immutable connector events remain authoritative. After sync, Alfred deduplicates revisions into daily JSON rollups and course/calendar profiles (exams, quizzes, assignments, ordinary events), retaining each source-event ID. Academic questions retrieve a few matching rollups rather than scanning raw history; rebuilding skips when the source fingerprint is unchanged. A second pass promotes current items into source-linked semantic memories, supersedes changed provider versions, and connects calendar/course entities to the owner graph. This never delays a chat reply.
The runner refreshes a three-year Calendar window weekly by default without
replacing Calendar's live incremental cursor. Canvas keeps upcoming/missing
on the normal interval and scans accessible course assignments once daily.
--calendar-history-days 0 disables Calendar history;
--calendar-history-interval and --canvas-history-interval tune it.
One-shot: calendar-history-sync --all-selected --days 1095 and
academic-memory-rebuild. Rollup JSON is a replaceable cache, not the
canonical archive—edits, cancellations, provenance, and forget/correction
stay in SQLite. Cognee is not a source of truth; it can be evaluated later
as an optional retrieval backend against the same source-linked memory tests.
As a real Windows service (survives logoff/reboot)
alfred-service packages the exact same loop as a Windows service,
independent of any logged-in session, using Windows' own recovery options for
restart-on-crash. It's a thin wrapper, not a separate code path: it drives
the identical construction/cleanup logic alfred run uses, built from
arguments parsed by the same parser.
# 1. Store the exact 'alfred run' arguments the service will launch.
.\.venv\Scripts\alfred service-configure run --pair 123:456 --chat-id 123
# 2. Install and start the service (requires an Administrator prompt).
.\.venv\Scripts\alfred-service --username ".\<your-windows-username>" --password "<your-windows-password>" install
.\.venv\Scripts\alfred-service startThe --username/--password are not optional. Every connector
credential lives in your Windows account's DPAPI-protected Credential
Manager, which only your account's own logon session can decrypt. Installing
without --username (or via the Services MMC snap-in's default) runs as
LocalSystem—the service will install and start "successfully," then die
immediately with missing local credential-store secret: .... Options must
precede the verb; getopt stops parsing at the first non-option argument, so
alfred-service install --username ... silently ignores the flags. The
password is visible in shell history once typed this way; clear it afterward
(Clear-History and/or remove the relevant line from
(Get-PSReadLineOption).HistorySavePath), or use the Services MMC snap-in
(services.msc → Alfred Personal Secretary → Log On tab) to set the account
without it touching a shell.
alfred-service debug runs the service logic in your current console instead
of under the SCM, printing exceptions directly instead of routing them
through Get-WinEvent.
Check on it with Get-Service Alfred, stop it with
.\.venv\Scripts\alfred-service stop, and remove it with
.\.venv\Scripts\alfred-service remove. Changing configured arguments
(re-run service-configure) needs a restart to take effect. Optionally
configure automatic restart on an unexpected crash—Windows services don't
retry by default—with:
sc.exe failure Alfred reset= 86400 actions= restart/60000alfred-service needs pywin32, already
pulled in transitively by the mcp package on Windows; if importing it
fails, run python .\.venv\Scripts\pywin32_postinstall.py -install once.
Installing, starting, stopping, and removing the service are Administrator
actions you run yourself—Alfred never elevates or registers itself.
Restart Alfred from your phone
When Alfred is running, Telegram accepts three operator commands from paired chats:
/status— is the loop alive, and when did it last cycle?/restart— restart now/wake— same as/restartwhen Alfred is down
Register the watchdog once (Administrator PowerShell, after
service-configure):
.\scripts\register-watchdog.ps1That creates two Task Scheduler entries:
AlfredWatchdog — every five minutes, runs
alfred watchdog-check. If the heartbeat is stale, it restarts the Windows service (or falls back to the configuredalfred runcommand from.alfred/service.json) and does one Telegram poll for/wakeor/restart.AlfredRestart — on-demand restart used by
/restartand the watchdog, with highest privileges so your phone does not need an Administrator prompt each time.
The runner writes a heartbeat every cycle, so a hung or dead process is picked
up automatically within a few minutes even if you do nothing. When Alfred is
fully stopped, send /wake from Telegram; the next watchdog pass sees it and
starts Alfred back up.
Local memory graph
alfred remember "statement" stores a confirmed local memory;
alfred memory-search "query" returns FTS anchors plus one active graph hop.
Corrections never rewrite history: alfred memory-correct --memory-id ID "corrected statement" marks the old memory superseded and creates a new one
that points back to it.
Deleting is preview-then-confirm, because deleting data is strong-confirm and
never unattended. alfred memory-forget-propose --memory-id ID --actor nico [--reason "..."] previews a scoped, single-item deletion. Approve it, then
alfred memory-forget-execute tombstones the memory, drops it from search,
and records an audit entry. A superseded memory stays visible as history
until it is separately forgotten.
alfred memory-alias --entity-id ID "Alternate Name" adds a searchable
alternate name—memory-search finds it by either name immediately after.
alfred memory-rename --entity-id ID "Real Name" changes what an entity is
actually called. People discovered from your calendar arrive labelled with
whatever Google supplied, which is sometimes just an email address; this is
how you fix that. The old label is kept as an alias, so existing
[[wiki links]] keep working—renaming is not forgetting.
Alfred fills names in on its own where it can: if someone's calendar address
also appears as a Gmail sender with a display name, the next people sync
adopts it. Gmail is only ever read for names, never to decide that someone
exists—your inbox is mostly brands, and a display name there is branding
rather than identity.
Obsidian vault
alfred vault-export-entity --entity-id ID and alfred vault-export-memory --memory-id ID (both take --vault PATH, default alfred-vault) project one
graph record into Generated/—plain, portable Markdown with an alfred_id
and managed: true in frontmatter. A hand-edited file in that path is never
silently overwritten; it's preserved and the projection instead becomes an
.alfred-conflict-<timestamp>.md copy for review.
Bulk exports select a set rather than one record:
.\.venv\Scripts\alfred vault-export-source-event --source-event-id ID
.\.venv\Scripts\alfred vault-export-range --since 2026-03-01 --until 2026-04-01
.\.venv\Scripts\alfred vault-export-topic "rowing" --limit 50
.\.venv\Scripts\alfred vault-export-person --entity-id IDvault-export-person defines "about a person" structurally: a memory is
about someone when it came from an event they organized, not when their name
appears in the wording. Text matching would treat "lunch near Robin's
office" as a memory about Robin—tolerable for an export, wrong for a
deletion, and this selector serves both. Find the entity ID with
alfred memory-search "<name>".
--since/--until filter on when Alfred recorded a memory, not when the
fact became true. The range is half-open (--since inclusive, --until
exclusive) so back-to-back months don't both claim a memory on the boundary.
Either bound can be omitted for an open-ended range, but not both. The topic
selector runs the same search a question would. Every bulk export writes only
confirmed, public/personal memories; anything skipped is reported by ID
rather than silently dropped. A topic export's receipt records that it was
a topic export, never the query you typed.
alfred vault-import --vault PATH reads the other direction: any
user-authored note anywhere in the vault (not just Generated/) becomes a
confirmed, evidence-backed memory. It's a scan you call periodically—via the
CLI, or automatically as a connector when alfred run is given --vault—not
an OS-level file watcher. Alfred never writes back to an imported file;
change detection is tracked in Alfred's database by content hash, so editing
a note supersedes its memory and deleting a note from disk does not delete
the memory it produced—only forget does that. Files Alfred itself generated
(managed: true) are never re-imported as testimony.
Import also reads [[wiki links]] (including [[Note|display]] and
[[Note#Heading]]). When a link names exactly one entity Alfred already
knows—by label or alias, case-insensitively—it's recorded as evidence that
this note concerns that entity. An unknown name creates no entity, an
ambiguous name resolves to nothing rather than guessing between two "Alex"
entities, and no relationship edge is created. The result reports linked
and unresolved_links.
Optional mobile sync
Alfred does not use paid Obsidian Sync. deploy/couchdb/ sets up the
self-hosted CouchDB service; read deploy/couchdb/README.md before running
it. Alfred's own code never syncs the vault to a phone; a vetted, open-source
Obsidian community plugin (Self-hosted LiveSync) does that entirely
client-side, replicating only alfred-vault/, never alfred.db, secrets, or
logs. alfred vault-sync-status --url http://127.0.0.1:5984 confirms the
server side is reachable.
MCP server
alfred-mcp runs Alfred's stdio MCP server for Claude Desktop/Code, Cursor,
and other local MCP clients. Every tool is default-deny: a client gets
nothing until explicitly granted, e.g. alfred client-grant --client-id local-mcp --sensitivity public --sensitivity personal --tool memory_search --tool remember --tool forget --tool calendar_event_propose --tool message_draft --tool action_commit --tool brief_get --tool connector_status --allow-write. alfred-mcp --client-id <id> runs it under a different
identity (default: local-mcp) so a second stdio client—for example OpenAI's
Secure MCP Tunnel—gets its own separately scoped grant.
Current tools: system_status, agenda_get, memory_search, profile_get,
remember, forget, calendar_event_propose, message_draft,
action_commit, brief_get, connector_status, task_upsert,
task_complete, and reminder_set—all 12 of section 7's documented tools,
plus system_status and calendar_event_propose (which action_commit
needs, since section 7 never names a tool for previewing a calendar write).
remember/forget additionally check the requested memory's sensitivity
against the client's own scope, so a client granted only public/personal
cannot write or erase a secret memory even with --allow-write.
forget, calendar_event_propose, message_draft, and
message_send_propose only preview. action_commit performs whatever a
previous tool call previewed, once given a fresh approval token. There is
deliberately no MCP tool to approve one. action_commit mints a fresh Google
access token itself when finishing a calendar write, Gmail draft, or Gmail
send; nothing is cached. Gmail sends remain explicit, one-time
approval-gated actions and never run from sync or a scheduled job.
Repeated-workflow proposals
When Hermes is enabled, Alfred performs a local workflow scan once per day.
It looks for the same successful two-to-eight-tool sequence at least three
times across two days. It stores only structural metadata: tool names,
argument names, and allowlisted routing labels such as connector type. It
does not store prompts, email bodies, task or event titles, people,
addresses, dates, identifiers, or arbitrary argument values. Failed turns and
turns that contain action_commit are ineligible.
.\.venv\Scripts\alfred workflow-scan
.\.venv\Scripts\alfred workflow-list --state pending
.\.venv\Scripts\alfred workflow-show --version-id <ID>
.\.venv\Scripts\alfred workflow-accept --version-id <ID>
.\.venv\Scripts\alfred workflow-reject --version-id <ID>Each suggestion is an inert, versioned SKILL.md plus a unified diff and an
expiring review record. Accepting the diff records that decision but this
first slice cannot activate or execute a generated skill; unattended learning
can produce review material but cannot modify the Hermes profile. Raw daily
Calendar/Canvas JSON snapshots are not used here: their normalized source
records already preserve provenance and change history.
Streamable HTTP (remote/private clients)
alfred-mcp is stdio-only. For a client that can't spawn a local process—or
that should run as a separate identity from local-mcp—alfred mcp-http-run --client-id <id> serves the same tool surface over Streamable HTTP on
http://127.0.0.1:8000/mcp. The host is not configurable: this binds
loopback only. <id> needs its own client-grant first, exactly like a
stdio client.
Every request must carry Authorization: Bearer <token>, checked outside
FastMCP's own request handling so an unauthenticated caller can't even open a
session. Generate that token once with alfred mcp-http-token-generate
(refuses to overwrite an existing one, same as backup-key-generate); it's
stored in the OS credential store, never in a config file. This is a single
shared secret, not OAuth—OAuth 2.1/RFC 9728 is reserved for public remote
access, a separate undertaking this does not attempt. FastMCP also
auto-enables DNS-rebinding protection (Host/Origin header validation)
whenever the host is loopback, which is always true here.
ChatGPT (Secure MCP Tunnel)
ChatGPT can't connect directly to a local MCP server the way Claude
Desktop/Cursor do over stdio, so OpenAI's Secure MCP
Tunnel is
the private-access path—an outbound-only relay via OpenAI's own
tunnel-client daemon, run by you, which Alfred does not vendor or
reimplement. See deploy/openai-tunnel/README.md for the walkthrough:
creating a tunnel and scoped client grant, then pointing tunnel-client at
alfred-mcp --client-id chatgpt-tunnel over stdio (deliberately not the
Streamable HTTP transport above, to avoid reconciling two authentication
schemes). Whether your ChatGPT plan supports custom MCP connectors at all is
between you and OpenAI.
Admin dashboard
alfred admin-ui-run serves a small, read-only web dashboard: today's
agenda, pending approvals, connector health, evaluation signals, and the
recent audit trail, at http://127.0.0.1:8200. One page per concern, no write
actions (approving still goes through alfred approval-approve, never a
button on this page). No CDN fonts or icons; it works with the network off.
.\.venv\Scripts\alfred admin-ui-token-generate
.\.venv\Scripts\alfred admin-ui-runDefaults to loopback-only like mcp-http-run, but unlike it, --host is a
real option—this is meant for a person to look at, sometimes from a phone.
127.0.0.1 is not reachable from another device even over a VPN; to check
it from your phone, run alfred admin-ui-run --host <this-PC's-VPN-IP> (a
Tailscale IP, for example—tailscale ip -4), never --host 0.0.0.0 unless
you already have firewall rules restricting who can reach the port. Works in
any modern browser; the layout reflows for a phone-width screen and uses the
system font (Segoe UI on Windows, San Francisco on Safari/iOS).
Auth is the same bearer token as mcp-http-run, delivered differently:
visiting any page without one redirects to a login screen; entering the token
there sets an HttpOnly, SameSite=Strict cookie whose value is the token
(no separate session store). Scripted/API access can still send
Authorization: Bearer <token> directly and skip the cookie.
Local vector search (optional)
MemoryGraph accepts an optional embedding_provider. Without one,
memory-search stays FTS5 keyword-only. With one—for example
alfred.embeddings.OllamaEmbeddingProvider, pointed at a local
Ollama—remember, memory-correct, and forget also keep a versioned
vector per memory in the embeddings table, and memory-search folds in
nearby vector matches (within a cosine-distance cutoff) once keyword hits are
exhausted. Vectors are namespaced by model name, so trying a different
embedding model never mixes incomparable spaces; switching models means
re-embedding, not migrating data. Run memory-embed-backfill --model nomic-embed-text for a one-shot rebuild, or pass --embedding-model nomic-embed-text to alfred run for continuous local upkeep.
Local model inference (optional)
alfred.models.OllamaClient is local-first text generation: point it at a
running Ollama and it calls the non-streaming /api/generate endpoint,
returning the text plus Ollama's own prompt/completion token counts.
BriefingService accepts an optional llm_writer; without one,
write_brief() is just render()—the deterministic text, unchanged. With
one, the model only ever rewrites the deterministic render's wording; every
fact, date, and link it sees comes from that text, never from the model's own
knowledge, and a failed or unreachable model falls back to the deterministic
render rather than costing the user their brief. Every pass is audited with
its token counts. Nothing in the CLI, MCP server, or job runner wires a live
writer in by default.
Cloud pieces are also built: alfred.models.OpenAICompatibleClient and
AnthropicCompatibleClient speak the OpenAI chat-completions and Anthropic
Messages API shapes, but neither should be constructed bare—wrap either in
GuardedCloudProvider first, which enforces:
Redaction.
Redactorscrubs common secret/PII shapes (emails, bearer tokens, OpenAI/GitHub/Slack/AWS key patterns, SSNs, card-like digit runs, phone numbers) from the prompt and system text before either reaches the cloud provider. It's a best-effort pattern scrub, not a guarantee—keep genuinelysecret-tagged content out of a cloud prompt rather than relying on this to catch it.Monthly hard cap, fail closed.
monthly_budget_usddefaults to0.0, so an unconfiguredGuardedCloudProvidernever calls out at all. Every call checks month-to-date spend (summed from its own audit records) before calling; once that's already at or past the cap, it raisesCloudBudgetExceeded. This checks the cap before each call, not a per-call ceiling—one very large call can still push the total over.Cost tracking. Every call, success or failure, is audited with the model name, prompt/completion token counts, and an estimated USD cost (from an operator-supplied
CloudPricing, since this module hardcodes no vendor price table)—never the raw prompt or response text. That audit trail doubles as the spend ledger requirement 2 reads from.
As with Ollama, nothing in the CLI, MCP server, or job runner constructs a cloud provider by default—an operator wires one in from their own configuration when they want it.
Development rules
Read ARCHITECTURE.md before changing behavior.
Keep the database as the source of truth; transports do not contain business logic.
Do not place credentials, raw personal data, or local databases in Git.
Every MCP tool is gated by
PolicyStore; an unregistered or narrowly scoped client gets nothing by default. Consequential actions on the MCP surface can only create previews; a human must approve them outside that MCP client beforeaction_commitcan execute the exact approved preview.
See CONTRIBUTING.md for the full local setup, test, and PR workflow, SECURITY.md to report a vulnerability privately, and RELEASING.md plus CHANGELOG.md for how a version gets cut and verified.
License
Apache-2.0. See LICENSE.
Available Tools
33 toolsaction_commitBDestructiveIdempotent
Consume a fresh approval token and perform the action it previewed.
| Name | Required | Description | Default |
|---|---|---|---|
| token | Yes | ||
| approval_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructive and idempotent behavior, so the description does not need to repeat those. It adds the useful behavioral fact that the token is consumed and must be fresh, and that the action was previously previewed, but it does not describe failure behavior or post-consumption consequences.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, front-loaded sentence with no filler. It conveys the action, the key precondition, and the source of the action in just nine words, which is appropriately concise for a simple two-parameter tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has only two primitive string parameters, no output schema, and annotations already cover destructive/idempotent/open-world aspects. The description establishes the critical precondition (fresh token) and the effect (perform previewed action), which is sufficient for this low-complexity commit tool, though it could still mention what happens if the token is stale.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the tool description must compensate for undocumented parameters. It only loosely clarifies the token as an 'approval token' and provides no additional meaning for approval_id or how the two fields relate, leaving a real gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly says the tool consumes an approval token and executes the action that was previewed, which identifies a specific commit/execute role in an approval flow. It does not explicitly name a sibling alternative, but the distinction from the many propose/draft siblings is implicit and adequate.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'consume a fresh approval token' implies this is the step to run after an approval has been obtained, and this is useful guidance. However, the description does not explicitly say when not to use it or name alternatives such as proposal or draft tools, leaving some inference required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
agenda_getARead-only
Return Alfred's deterministic local task agenda with freshness.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the description does not need to restate that. It adds the behavioral context of 'deterministic' and 'local', which is useful, but 'with freshness' is vague and does not disclose what freshness means or how it affects results. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, compact sentence that states exactly what the tool does. No filler or redundant phrasing, and the core message is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a parameterless, read-only tool with an output schema present, the description is mostly complete. The one gap is the ambiguous 'with freshness' clause, which could be interpreted as return freshness metadata or a guarantee of up-to-date data. Overall the agent can invoke it correctly without further information.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so there are no parameter details to document. The baseline for 0 parameters is 4; the description does not add parameter information but does not need to since none exist.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Return') and names a clear resource ('Alfred's deterministic local task agenda'), which distinguishes it from sibling tools like system_status or memory_search. The qualifiers 'deterministic' and 'local' further pin down what this tool uniquely provides.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this tool versus its many siblings. No mention of conditions, alternatives, or exclusions. The agent is left to infer that agenda_get is for reading Alfred's task agenda, but not when that is preferable to task_complete or availability_get.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
availability_getARead-only
Find free gaps in the synced Google Calendar over the next few days.
Timed events block the day; all-day events are listed as ambiguous
context rather than busy hours. Overlapping meetings merge before gaps
are computed. timezone is an IANA name; default working hours are
09:00–17:00 local.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | ||
| timezone | No | UTC | |
| min_minutes | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses several non-obvious behaviors beyond the readOnlyHint annotation: timed events block the day, all-day events are ambiguous context, overlapping meetings merge before gap computation, and default working hours are 09:00–17:00 local. This materially helps an agent interpret results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded, with each sentence adding behavioral or parameter meaning. There is no filler or repetition of schema fields.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only search tool with an output schema and annotations, the description covers important edge cases: all-day events, overlap merging, timezone handling, and working-hour defaults. Nothing critical is missing for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It clarifies timezone as an IANA name and links days to the next-few-days horizon, but it never explicitly defines min_minutes as the minimum free-gap duration, leaving one parameter under-specified.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Find free gaps in the synced Google Calendar.' It clearly differentiates availability lookup from siblings like agenda_get or calendar_event_propose by focusing on gap detection rather than event listing or proposal.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when to use the tool: finding open time slots in a synced calendar. It does not explicitly name alternatives or exclusion conditions, but the context is strong enough for an agent to select it appropriately among the listed siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
brief_getARead-only
Render the deterministic local morning brief on demand, not just on schedule.
| Name | Required | Description | Default |
|---|---|---|---|
| now | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnlyHint already establishes the tool is safe to call, and the description adds useful behavior: the output is deterministic, local, and generated on request rather than by schedule. This goes beyond the annotation without contradicting it. Return details are covered by the output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single tight sentence with the core action front-loaded and the scheduling contrast in a short secondary clause. Every phrase contributes meaning and there is no redundant restatement of the tool name or schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a low-complexity, read-only tool with no required parameters and an existing output schema, the description covers purpose and usage well. The only meaningful omission is the optional 'now' parameter, but it has a sensible default and is not required for normal invocation, so the definition is still largely complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description needed to explain the lone 'now' parameter — its format, meaning, and how null behaves. The word 'deterministic' hints that 'now' controls the evaluation time, but the description never explicitly mentions or documents the parameter, leaving a real invocation gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb ('Render') and a distinct resource ('the deterministic local morning brief'), and clarifies the invocation mode ('on demand, not just on schedule'). This gives the tool an identity separate from sibling tools like agenda_get or journal_get.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly states when to use the tool: whenever an on-demand morning brief is needed instead of waiting for the scheduled one. It does not name explicit alternatives or when-not-to-use conditions, so it stops short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_event_proposeA
Preview a calendar event write; nothing reaches Google until action_commit confirms it.
start and end must be ISO 8601 timestamps, not phrases. The owner says "tomorrow from 10:30 am"; resolve that against the current time given above and pass 2026-08-20T10:30:00-04:00.
calendar_id accepts the name the owner uses -- "family car", "Dunlap Family" -- as well as a real Google id. Pass whatever calendar they named; it is resolved here, and an unknown or ambiguous name comes back as an error listing the writable calendars rather than guessing.
| Name | Required | Description | Default |
|---|---|---|---|
| end | Yes | ISO 8601 timestamp, e.g. 2026-08-20T10:30:00-04:00. Not a phrase. | |
| start | Yes | ISO 8601 timestamp, e.g. 2026-08-20T10:30:00-04:00. Not a phrase. | |
| summary | Yes | ||
| calendar_id | No | primary |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the annotations by disclosing that no external write happens until confirmation, that natural-language date phrases must be resolved to ISO 8601 timestamps, and that calendar_id accepts both friendly names and real Google ids. It also reveals the error behavior for unknown or ambiguous calendar names: return a list of writable calendars rather than guessing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well structured: the opening sentence delivers the core purpose immediately, and the following paragraphs each add a distinct operational detail needed for correct invocation. There is no filler or repetitive explanation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the safety model, the timestamp requirements, calendar_id resolution behavior, and failure behavior. It does not describe what a successful preview response contains, but for a preview tool whose main contract is 'no side effects until commit,' this is only a minor gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 50%, so the description compensates by adding meaning to start, end, and calendar_id. It explains timestamp formatting and resolution, and it clarifies how calendar names are handled. Only summary lacks explicit guidance, though its purpose is reasonably inferable from the context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific action and resource: 'Preview a calendar event write.' It also explains the two-phase nature by stating that nothing reaches Google until action_commit confirms, which clearly distinguishes this preview tool from a direct commit or create tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The intended use is clear: this is the preview step before action_commit, and the description gives practical instructions for resolving date phrases and passing calendar names. It does not explicitly enumerate when not to use it, but the context and sibling name action_commit make the workflow unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
composio_connectA
Return a Composio Connect Link so the owner can sign into an overflow app.
Open the URL, finish sign-in, then retry the original request. Not for Gmail/Calendar/GitHub/Slack/Telegram/Fitbit.
| Name | Required | Description | Default |
|---|---|---|---|
| toolkit | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description discloses that the tool returns a user-facing link and that the sign-in flow is interactive: the owner must open the URL and complete sign-in before retrying. This is important behavioral context. It does not mention side effects or connection state changes, but the annotations do not contradict the description.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three terse sentences with no filler: purpose is front-loaded, then the required follow-up workflow, then the exclusions. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with one parameter and no output schema, the description covers the interactive flow and exclusions well. However, it omits valid toolkit values and doesn't explain how to verify the connection after sign-in, so an agent could still invoke it with an unsupported toolkit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The only parameter, 'toolkit', has no schema description (0% coverage), and the description never explicitly explains what to pass. The exclusion list implies it selects an integration, but no valid values or examples are given, so an agent may not know what to pass for an allowed app.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete verb ('Return') and resource ('Composio Connect Link') with a clear purpose: letting the owner sign in to an app. The phrase 'overflow app' is somewhat vague, and it doesn't explicitly differentiate from sibling Composio tools, so it isn't a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides a clear workflow: open the returned URL, finish sign-in, then retry the original request. It also gives a concrete exclusion list ('Not for Gmail/Calendar/GitHub/Slack/Telegram/Fitbit'). It stops short of naming alternative sibling tools or conditions for when to use composio_status or composio_execute instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
composio_executeA
Run a Composio read now, or preview a write for Telegram approval.
arguments_json is a JSON object matching the tool's input fields from
composio_search. Writes return needs_approval; never call action_commit.
| Name | Required | Description | Default |
|---|---|---|---|
| slug | Yes | ||
| arguments_json | No | {} |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With readOnlyHint and other annotations all false, the description carries the burden of disclosing behavior. It adds valuable detail: reads execute immediately, writes are only previewed for Telegram approval, and action_commit must not be called. It stops short of explaining the post-approval flow, but the core behavioral warning is present.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three short sentences with no filler. The purpose is front-loaded, and the critical warning about action_commit is placed last without diluting the main instruction.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter tool with no output schema, the description covers the execution mode, the argument source, and the approval/commit warning. Missing slug semantics and read return behavior are minor gaps but leave some ambiguity for an agent that lacks broader Composio context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It explains arguments_json as a JSON object matching input fields from composio_search, which is useful, but it does not explain slug beyond its name or how to obtain a valid slug. The compensation is incomplete.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb and resource: run a Composio read now, or preview a write for Telegram approval. It also distinguishes itself from the sibling action_commit by explicitly saying never call action_commit, so the agent can tell its role apart from related tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives actionable context: arguments_json should match fields from composio_search, writes return needs_approval, and action_commit should not be called. It does not fully spell out the complete search-then-execute flow, but the usage context is clear enough to route an agent correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
composio_searchARead-only
Find overflow-app tools on Composio's free tier (Notion, Spotify, Linear, …).
Do not use this for Gmail, Calendar, GitHub, Slack, Telegram, or Fitbit — those are first-party Alfred connectors. Returns slugs, whether they write, and required argument names. Then call composio_execute with a slug.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| toolkit | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false. The description adds that results include slugs, whether the tool writes, and required argument names, which goes beyond the annotations. It does not discuss rate limits or auth, but for a read-only search tool this is a minor gap, not a contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: it states the purpose first, gives exclusions, and closes with the exact follow-up action. Every sentence earns its place with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only search tool, the description covers purpose, exclusions, return contents, and the next step, which is sufficient for an agent to invoke it correctly. The only material gap is the unexplained optional toolkit parameter, which prevents a perfect score.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry the semantic load for the parameters. It does not explain what 'query' should contain beyond the general search context, and it entirely ignores the 'toolkit' parameter, which is undocumented in both the schema and the description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific action and target: 'Find overflow-app tools on Composio's free tier' with concrete examples. It also distinguishes the tool from first-party Alfred connectors and from composio_execute, the follow-up call, so an agent can tell them apart.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says when not to use this tool: 'Do not use this for Gmail, Calendar, GitHub, Slack, Telegram, or Fitbit' because those are first-party Alfred connectors. It also names the next step, composio_execute, and says to call it with a slug.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
composio_statusARead-only
Show Composio connected accounts and this UTC month's free-tier usage.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description is consistent with the readOnlyHint=true annotation and adds useful context beyond it: the specific UTC month scope and what the tool reports. No destructive or mutating behavior is suggested.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One concise sentence that front-loads the resource and delivers the complete meaning. There is no filler or redundant restatement of the tool name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only status tool with no output schema, the description fully specifies what the agent can expect. Nothing needed to decide whether to call it is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are no parameters, so the description carries no parameter burden. Baseline for zero-parameter tools is 4, and the description correctly specifies the tool's informational output.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Show') with a clear resource and scope: Composio connected accounts plus this UTC month's free-tier usage. This distinguishes it from sibling tools like composio_search, composio_execute, and composio_connect.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The intended use case is clear: call this tool when reporting on Composio connected accounts or current monthly free-tier usage. It does not explicitly name alternatives or exclusions, but the zero-parameter read-only status nature makes the context sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
connector_records_getARead-only
Return one connector's currently-active synced records, most recently observed first.
brief_get/agenda_get already fold calendar events, GitHub notifications, and Canvas missing assignments into one ranked digest, but nothing else exposes a connector's raw synced content directly -- for example gmail-sync's unread-message records (subject/from/snippet) never reach an MCP caller otherwise. This reads the same connector_records table every sync already writes to (ConnectorRecordStore), so it needs no new storage or sync logic.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| connector | Yes | ||
| record_type | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, and the description adds behavioral context beyond that: it reads the connector_records table that syncs write to, requires no new storage or sync logic, and returns only currently-active records in reverse chronological order. This is useful and consistent with the read-only annotation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The first sentence is a clear, front-loaded definition of behavior. The following paragraph is somewhat long but each sentence serves a purpose: differentiating from sibling tools and clarifying that no new storage or sync logic is needed. It is appropriately detailed without filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only tool, the description covers what it returns, ordering, data source, and how it differs from digest tools. However, because schema-level parameter documentation is entirely absent and the description does not define record_type or limit semantics, an agent may still be uncertain how to correctly invoke the tool for a specific record type.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has no descriptions (0% coverage), and the description does not explain the limit or record_type parameters, their defaults, or accepted values. It only clarifies the connector scope and gives one example involving gmail-sync unread-message records, leaving the agent to guess how filtering and limiting actually behave.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific action and resource: 'Return one connector's currently-active synced records, most recently observed first.' It also explicitly contrasts this tool with brief_get and agenda_get, positioning it as the only direct accessor of raw connector content, so it is clearly distinguishable from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context by stating that brief_get/agenda_get provide a folded digest, while this tool exposes raw synced records directly. It doesn't explicitly say 'use this when you need raw records and use brief_get/agenda_get when you need a digest,' but the contrast is strong enough to guide selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
connector_statusARead-only
Report each connector's health; never its credentials or synced content.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, covering the tool's non-mutating nature. The description adds a useful behavioral guarantee beyond annotations: the report excludes credentials and synced content, which is important contextual information for an agent. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence that front-loads the operation and resource, then immediately constrains the scope with a clear exclusion. Every word contributes meaning; there is no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a parameterless, read-only status tool with an output schema, the description is complete. It states what is reported, what is deliberately excluded, and the annotations cover mutability. No critical information needed to invoke the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has zero parameters and schema coverage is 100%, so there is no missing parameter documentation to compensate for. The description reinforces the no-argument aggregate nature by saying 'each connector's health' rather than implying a single-connector filter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource ('Report each connector's health') and clarifies what the report will never contain ('credentials or synced content'). It clearly states the tool's purpose, though it does not explicitly name sibling tools like composio_status or connector_records_get to sharpen differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'never its credentials or synced content' provides an explicit when-not boundary, steering agents away from using this tool for credential or content retrieval. However, it does not name alternative tools or state when to prefer this tool over system_status or composio_status.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
forgetA
Preview deleting one memory; nothing is deleted until action_commit confirms it.
Decision 8 classifies deleting data as strong-confirm, never unattended, so an MCP client -- which can call tools without a human watching in the moment -- cannot delete in a single call.
| Name | Required | Description | Default |
|---|---|---|---|
| reason | No | user requested deletion | |
| memory_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses that despite the name 'forget', this tool is not destructive by itself and that deletion is deferred until action_commit confirms. It adds meaningful policy context about strong-confirm and unattended MCP clients, which is especially valuable given destructiveHint=false could otherwise be confusing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The first sentence is clear and front-loaded with the core behavior, and the second provides important policy context. The phrasing is a bit verbose and relies on unexplained 'Decision 8' jargon, but every sentence contributes meaningful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description explains the critical two-phase behavior and client safety constraint, but it omits details about what the preview response looks like, what happens to pending deletions before commit, and how the reason parameter is used. Since there is no output schema, additional behavioral detail would improve completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the description does not explain the meaning or usage of memory_id or reason. The tool's purpose implies memory_id identifies the memory, but reason is left entirely unexplained, so the description does not compensate for the missing parameter documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Preview deleting') and resource ('one memory'), and immediately clarifies the key limitation that nothing is deleted until action_commit confirms it. This distinguishes the tool from action_commit and makes its role in the deletion workflow clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains the two-phase workflow and explicitly warns that an MCP client cannot delete in a single call because deleting data is classified as strong-confirm. It does not enumerate alternatives, but it names action_commit as the confirming step, giving enough context for when to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
github_issue_proposeA
Preview a GitHub issue creation; nothing reaches GitHub until action_commit confirms it.
| Name | Required | Description | Default |
|---|---|---|---|
| body | No | ||
| title | Yes | ||
| repository | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Despite readOnlyHint=false, the description discloses that no external write reaches GitHup until a later commit — genuinely load-bearing context beyond what the annotations provide. This also aligns with destructiveHint=false and clarifies the non-idempotent preview trait. It doesn't cover auth requirements or failure modes, but the core safety trait is disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with zero waste, front-loading the primary purpose ('Preview a GitHup issue creation') and then the critical behavioral caveat. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 3-parameter tool with no output schema, the description covers purpose, the preview/commit boundary, and names the committing sibling. A minor gap is that it doesn't hint what the preview returns (e.g., a proposal to hand to action_commit), but the simple parameter set and annotations keep this adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the burden. It contextualizes repository/title/body as the components of a GitHup issue and implies they will later be committed, but it adds no per-parameter format or constraint details (e.g., 'owner/repo' syntax). The parameter names are self-evident, making the gap moderate rather than severe.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Preview') and resource ('GitHup issue creation'), and the second clause ('nothing reaches GitHup until action_commit confirms it') sharply differentates it from the complementary sibling action_commit. An agent can immediately tell this is the staging step, not the publishing step.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The second sentence explicitly places the tool in a two-phase workflow: preview here, confirm with action_commit. It names the sibling that completes the operation, which gives clear context for when to pair them. It does not enumerate when-not-to-use conditions, but the propose/commit boundary is explicit enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
gratitude_recordA
Append a free-text gratitude journal entry.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations are all false, so they do not convey safety or side effects. The description's 'Append' indicates a write operation, consistent with readOnlyHint=false, and it adds the 'free-text' qualifier, but it does not disclose persistence, error behavior, or any side effects beyond the obvious mutation. It neither adds rich context nor contradicts the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, front-loaded sentence with zero waste. Every word contributes to clarity, and the action ('Append') is stated first. It is appropriately sized for the tool's simplicity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter append tool with no output schema, the description provides enough to call it correctly: it identifies the resource, the action, and the nature of the parameter. It omits any mention of return values or side effects, but given the tool's simplicity and absence of an output schema, this is a minor gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. 'Free-text' clarifies that the 'text' parameter is the raw content of the journal entry with no formatting constraints, adding meaning beyond the bare string type. It does not specify limits or optionality beyond the required flag, but for a single free-text parameter this is adequate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Append') and resource ('gratitude journal entry'), clearly distinguishing it from siblings like mood_record (structured mood tracking) and journal_get (retrieval). The purpose is unambiguous and immediately actionable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus alternatives such as mood_record or journal_get. The simple action is implied, but the description does not explicitly state context or exclusions, leaving the agent to infer usage from the name and siblings alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
important_date_setA
Remember a birthday or other annual date and remind on that day each year.
Stored as an ordinary task (next occurrence as due_at) plus an annual
reminder job — not a separate calendar. The morning brief and weekly
window surface dates in the next seven days under Birthdays & dates.
timezone is an IANA name so the local morning of the date survives
daylight saving. year is optional and only used to say "turns N".
| Name | Required | Description | Default |
|---|---|---|---|
| day | Yes | ||
| kind | No | birthday | |
| year | No | ||
| label | Yes | ||
| month | Yes | ||
| chat_id | Yes | ||
| timezone | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds valuable behavioral detail beyond the annotations: it states that the date is stored as an ordinary task with a next-occurrence due_at plus an annual reminder job, and that dates surface in the morning brief under 'Birthdays & dates.' It also explains timezone behavior relative to daylight saving. This goes well beyond the minimal readOnly/destructive hints, though it does not disclose duplicate handling or update semantics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences with no filler: purpose, storage/surfacing behavior, and the two parameter clarifications that matter most. It is front-loaded with the primary use case and keeps supporting details compact. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given seven parameters, minimal annotations, and no output schema, the description covers the main operational context: recurrence model, where dates appear, timezone semantics, and year handling. It does not explicitly state what the response will be or how chat_id is used, but the overall behavior is clear enough for an agent to invoke it confidently in most cases.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It does explain the two least obvious parameters: timezone is an IANA name and year is optional and only used for 'turns N.' However, label, month, day, chat_id, and kind are left to their names or schema defaults; in particular, kind values beyond 'birthday' are not specified even though 'other annual date' is mentioned.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Remember a birthday or other annual date and remind on that day each year.' It clearly differentiates from calendar_event_propose by stating 'not a separate calendar' and from important_dates_get by the set-vs-get relationship. The purpose is unambiguous and immediately useful for tool selection.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a clear condition for use: recurring annual dates that should remind yearly. It implicitly excludes calendar events and one-off reminders by describing the storage as an ordinary task plus annual reminder job, and by mentioning the morning brief/weekly window. It does not explicitly name alternatives like reminder_set or calendar_event_propose, so the guidance is strong but not fully explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
important_dates_getARead-only
List upcoming birthdays and important dates inside the weekly window.
Defaults to seven days so a "what's coming up this week" question and the morning brief share the same horizon. Pass a larger window to look further ahead; pass 0 for only dates still later today.
| Name | Required | Description | Default |
|---|---|---|---|
| within_days | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as read-only, and the description adds practical behavioral detail: the default seven-day window, the effect of passing a larger window, and the meaning of passing 0. This goes beyond the annotation and helps the agent reason about results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact, front-loaded with the core purpose, and every subsequent sentence adds useful behavioral or parameter guidance. No wasted words or redundant restatement of the tool name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple, single-parameter read-only listing tool with an output schema, the description covers the essential semantics: what is listed, the default horizon, and how to override it. Nothing important is missing for an agent to select and invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description fully compensates by explaining the only parameter, within_days: its default, how to extend the window, and what 0 means. The parameter name clarifies the unit, so an agent can invoke it correctly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'List upcoming birthdays and important dates'. It also scopes the behavior to 'inside the weekly window', which distinguishes it from sibling tools like important_date_set and agenda_get without ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear usage context: it aligns with 'what's coming up this week' questions and the morning brief, and explains how to adjust the time horizon. It does not explicitly name alternative tools or say when not to use it, but the context is strong enough for an agent to know when this tool fits.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
journal_getARead-only
Return recent mood check-ins, gratitude entries, and mood trend.
Trend direction is only named when there are at least five days with mood
check-ins and the older/newer daily averages differ by at least 0.5 on
the 1–5 scale; otherwise mood_trend.reason explains the refusal so
a null direction does not read as "no change".
| Name | Required | Description | Default |
|---|---|---|---|
| days | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, the description reveals a non-obvious rule: trend direction is only named with at least five days of check-ins and a 0.5 difference, and otherwise mood_trend.reason explains the null. This prevents an agent from misreading a null trend as 'no change,' which is exactly the kind of hidden behavior that matters.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The first sentence is a clear front-loaded statement of function, and the second adds a necessary qualification about trend naming. Both sentences earn their place, and the prose is compact for the behavioral nuance it conveys.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description names the major return components (mood check-ins, gratitude entries, mood trend) and explains mood_trend's null behavior, so an agent understands what it will receive. It does not describe entry-level fields or ordering, but those are less critical for correct invocation given the simple optional parameter.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The only parameter, days, has no schema description and the description does not explicitly explain it, though 'recent' hints at the lookback window. The schema's type, name, and default make the parameter fairly self-evident, so the lack of additional detail is not severely penalized.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Return recent mood check-ins, gratitude entries, and mood trend.' This clearly identifies what the tool retrieves and distinguishes it from the record-creation siblings like mood_record and gratitude_record.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the tool is for retrieving recent journal/mood data, but it does not explicitly state when to use it over alternatives such as mood_record or gratitude_record. Usage must be inferred from the tool's name and domain rather than from direct guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_correctA
Correct one recalled memory while preserving its superseded history and evidence.
| Name | Required | Description | Default |
|---|---|---|---|
| memory_id | Yes | ||
| replacement_statement | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations are all false, so the description carries the burden of explaining behavioral impact. It usefully discloses that the operation preserves superseded history and evidence, indicating a non-destructive correction. It does not mention return values or failure behavior, which keeps it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence with no filler: the action is front-loaded and the preservation guarantee is stated compactly. It is appropriately concise for a simple two-parameter tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter mutation with no output schema, the description covers the core operation and its principal side effect. It is slightly thin on return or error semantics, but not critically incomplete for selecting and invoking the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the parameter names are fairly self-explanatory and the description reinforces the replacement intent. It does not explicitly define memory_id or replacement_statement, nor does it mention constraints such as whether the memory must already exist.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource ('Correct one recalled memory') and adds a distinguishing detail: preserving superseded history and evidence. This clearly separates it from sibling tools like memory_add, memory_delete, and even a plain memory_update.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The correction intent is clear, but the description does not explicitly state when to prefer this over memory_update or when not to use it. Usage is implied by the word 'Correct' rather than stated as a condition or with named alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_feedbackB
Record whether a recalled memory was relevant, irrelevant, or incorrect.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| outcome | Yes | ||
| memory_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations offer no safety signals, so the description carries the full burden. It does communicate that this records feedback and implies a write operation, but it does not disclose whether repeated feedback overwrites previous feedback, whether it is associated with a specific query, or what effect it has on future recall. For a mutating tool with no annotation support, this is a notable gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, focused sentence with no fluff. It front-loads the action and immediately defines the categories of feedback.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple three-parameter tool with no output schema, the description covers the core purpose and the expected feedback categories. It is adequate but incomplete: it does not explain the relationship between 'query' and 'memory_id', nor does it state when feedback should be recorded or what downstream behavior it influences.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and there are no enums. The description helps by naming the possible outcome values ('relevant, irrelevant, or incorrect'), which clarifies the 'outcome' parameter. However, it gives no explicit meaning or format for 'query' and 'memory_id', leaving those to be inferred from their names.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb, 'Record', and a clear resource: whether a recalled memory was relevant, irrelevant, or incorrect. This is concrete and actionable, though it does not explicitly differentiate itself from sibling tools like memory_correct beyond the word 'feedback.'
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The context of use is implied: it is for recording feedback about a recalled memory. However, it does not explicitly state when to use this over memory_correct, forget, or other memory-related sibling tools, nor does it mention prerequisites like having a memory_id from a prior search.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_searchARead-only
Search local memory anchors and their one-hop active graph context.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate safe read-only behavior (readOnlyHint=true), so the description need not repeat that. It adds some behavioral context by limiting the search to 'local memory anchors' and 'one-hop active graph context', but it does not disclose result pagination, matching semantics, or other runtime behavior. This is adequate but not rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, front-loaded sentence with no filler. Every word carres meaning: 'Search' gives the operation, 'local' scopes it, and 'one-hop active graph context' defines the extent of results.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only search tool with one required parameter, the description is mostly complete for invocation. However, with no output schema present, it does not fully describe the return format or how 'active graph context' is represented, leaving some ambiguity for an agent interpreting results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema only shows a required string 'query' with no meaningful description. The tool description minimally compensates by clarifying that the query searches local memory anchors and their one-hop graph context. It does not specify query syntax, matching behavior, or format expectations, so the meaning is only partially covered.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Search'), a clear resource ('local memory anchors'), and a scope qualifier ('one-hop active graph context'). It is immediately distinguishable from the sibling memory tools like remember, memory_correct, memory_feedback, and forget, which are write/destructive operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The verb 'Search' implicitly conveys this is the tool for retrieving memory content rather than mutating it, but the description does not state when to prefer it over a sibling or mention any exclusions/alternatives. Usage is implied by the operation name, not explicitly guided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
message_draftA
Preview a Gmail draft; nothing reaches Gmail until a human confirms it.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | ||
| body | Yes | ||
| subject | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses a key behavioral guarantee beyond the annotations: no external side effect until a human confirms. This is valuable safety-relevant context. It does not contradict readOnlyHint=false because the tool may still perform local work or prepare a draft, but the key external behavior is clarified.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, front-loaded sentence communicats purpose and the most important behavior with zero waste. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is adequate for a simple preview tool and clearly states the safety guarantee. However, it does not describe the return value or what the agent should expect after invoking it, and param-level guidance is absent. With no output schema, this leaves a modest gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the description adds no additional meaning for to, subject, or body. The parameter names are self-explanatory, but no format, constraints, or examples are provided, leaving the description to carry the burden it does not shoulder.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Preview') with a clear resource ('Gmail draft') and adds a decisive scope qualifier: nothing reaches Gmail until human confirmation. This distinguishes it from send-oriented sibling tools like message_send_propose, even without naming an alternative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It implies usage: use this to preview before anything is sent or reaches Gmail. However, it does not explicitly state when to prefer this over alternatives, nor mention any exclusions or preconditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
message_send_proposeA
Preview sending Gmail. Telegram attaches approve/cancel; do not paste the letter in chat.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | ||
| body | Yes | ||
| subject | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the boolean annotations (all false), the description discloses a real behavioral trait: Telegram attaches approve/cancel buttons to this proposal. It also adds the operational instruction not to paste the letter into chat, which is useful context an agent would not get from the schema or annotations. It does not go into what happens after an approve, but the word 'preview' plus approve/cancel sufficiently conveys the interaction model.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short, purposeful sentences. The purpose is front-loaded in the first sentence, and the second sentence supplies the critical Telegram behavior and a safety instruction. There is no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple 3-string-parameter proposition tool, the description explains the workflow (preview, approve/cancel, avoid pasting body content) well enough for an agent to invoke it sensibly. It lacks parameter detail and does not specify the post-approval effect, but the approve/cancel model and the tool's propose semantics cover the main decision point.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description should compensate for the undocumented to/subject/body parameters. It only indirectly refers to 'the letter' and 'Gmail', providing weak semantic context, but it never clarifies the meaning or format of individual parameters. An agent still has to infer that 'to' is a recipient email address and 'subject' is an email subject.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific action and resource: 'Preview sending Gmail.' It clearly identifies the tool as the approval-gated send proposition for email, and the mention of Telegram approve/cancel distinguishes it from a plain drafting tool like message_draft. The purpose is unambiguous from the first sentence.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for use: this is the preview/send-proposal path for Gmail, and it explicitly warns the agent not to paste the email body into chat. It does not enumerate exclusions or name alternatives like message_draft, so it falls just short of fully explicit when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mood_recordA
Record a 1–5 mood check-in with an optional short note.
Stored separately from habits: mood tracks how things felt, not whether
a behavior happened. Use journal_get to review recent entries and
whether a trend can be named.
| Name | Required | Description | Default |
|---|---|---|---|
| note | No | ||
| rating | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate a non-read-only, non-destructive operation but give little else. The description adds that mood is stored separately from habits, which is useful context, but it does not specify whether each call appends a new entry or overwrites, nor does it mention any side effects or permissions. Given minimal annotation coverage, this is a moderate gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences with no waste: the first front-loads the core action and optional note, the second adds the distinction from habits and the pointer to journal_get. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple tool with only two parameters and no output schema, the description gives enough to call it correctly: the rating range, optional note, and the workflow for reviewing entries. It is complete for the tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description directly states the rating is on a 1–5 scale and that the note is 'optional short', which adds meaning beyond the bare schema (which has no descriptions). This compensates well for the 0% schema description coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear action ('Record') on a specific resource ('mood check-in') with a defined scale (1–5). It explicitly contrasts with habit tracking and points to journal_get for review, distinguishing it from sibling tools like gratitude_record and journal_get.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides a direct pointer to journal_get for reviewing entries and naming trends, implying this tool is for capturing data rather than analysis. While it doesn't list explicit exclusions, the context is sufficient for an agent to decide when to use this tool vs. alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
nag_until_doneA
Repeat a reminder until the linked task is completed or attempts run out.
Each firing re-reads task state, so completing the task anywhere silences future nags. The final attempt is labeled explicitly as the last reminder.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | ||
| chat_id | Yes | ||
| task_id | No | ||
| first_run_at | No | ||
| max_attempts | No | ||
| interval_hours | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations provide minimal safety info (readOnly=false, not idempotent, not destructive). Description adds meaningful behavior beyond annotations: each firing re-reads task state, completing the task anywhere silences future nags, and final attempt is explicitly labeled. This gives the agent essential operational expectations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences with key behavior front-loaded. Every sentence contributes: mechanism (repeat), termination conditions, re-read behavior, and final-attempt labeling. Could be more compact but no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 6-parameter tool with 0% schema coverage and no output schema, the description is inadequate. It explains the overall mechanism but omits parameter formatting/semantics entirely—most critically what text expects, how task_id links to a task, how first_run_at should be formatted, and the meaning of interval_hours. The return behavior is also unstated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden of parameter explanation, and it fails to do so. It never explains text, chat_id, task_id, first_run_at, max_attempts, or interval_hours. The behavioral description implies some parameter meanings (task, attempts, reminders) but doesn't map parameters to their roles.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description states a specific verb+resource: repeats a reminder until task completion or attempts run out. Distinguishes itself from the sibling reminder_set by describing the conditional repetition behavior, though it doesn't name the sibling explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Description implies usage context clearly: use for reminders that should persist until the linked task completes. States the stopping conditions (task completion or attempts exhausted). Doesn't explicitly state when not to use it or name alternatives, but behavioral distinction is implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
profile_getARead-only
Return the local owner node and current, evidence-backed profile relationships.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, and the description does not contradict them. It adds useful content context ('local owner node', 'evidence-backed relationships') but does not provide deeper behavioral disclosures beyond what the annotations imply.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, tightly worded sentence with the verb front-loaded. Every word earns its place, and there is no redundant or promotional filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only tool with no output schema, the description is sufficiently complete. It names both components of the return value (local owner node and profile relationships) and the complexity is low enough that little else is needed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and full schema coverage, so the baseline of 4 applies. There are no parameter semantics for the description to add.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Return') and a specific resource ('local owner node and current, evidence-backed profile relationships'). This clearly distinguishes the tool from its siblings and leaves no ambiguity about what it does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage context is implied by the tool name and the description, but there is no explicit statement about when to use profile_get versus alternative tools. It does not mention exclusions or provide routing guidance among the many sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pull_requests_getARead-only
List open GitHub pull requests you authored or were asked to review.
Fetches a live snapshot via GitHub search (not notifications sync),
marks PRs stale when updated_at is older than stale_after_days.
| Name | Required | Description | Default |
|---|---|---|---|
| stale_after_days | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this as read-only, lowering the burden on the description. The description adds useful behavior: it fetches live data via GitHub search and applies staleness logic based on updated_at and stale_after_days. The phrase 'marks PRs stale' is slightly ambiguous, but in a read-only list context it clearly means computed labeling rather than a mutation, so there is no contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two dense sentences with no filler. The main purpose is front-loaded, and the second sentence adds only high-value behavioral details about the live snapshot and staleness calculation. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a simple read-only tool with one optional parameter and an output schema. The description covers the resource, the selection criteria, the data source, and the one configurable behavior. There is nothing an agent needs to know in order to invoke it correctly that is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has 0% description coverage, so the description must explain the only parameter, stale_after_days. It does so by defining staleness as updated_at being older than that number of days, which gives the agent a clear semantic meaning. It does not state bounds or exclusivity, but the default is in the schema and the integer meaning is clear.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'List open GitHub pull requests you authored or were asked to review.' It clearly scopes the tool's behavior and distinguishes it from notification-based data by noting it fetches a live snapshot via GitHub search. No sibling tool appears to serve the same purpose, so the intent is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description tells the agent when to use the tool: whenever open PRs authored by or assigned to the user need to be listed. It also provides important context by clarifying this is a live search snapshot, not a notifications sync. It does not name an alternative tool, but none of the siblings directly compete, so the guidance is sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
rememberC
Store a confirmed local memory; the calling client is recorded as actor.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | note | |
| statement | Yes | ||
| sensitivity | No | personal |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already show this is a non-readonly, non-idempotent mutation, and the description adds the useful side effect that the calling client is recorded as actor. It does not disclose potential duplicate handling, overwrite behavior, scoping effects, or consequences beyond that. The added detail is meaningful but thin.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence states the core action and an important side effect with no filler. It is as concise as a useful description can be.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The definition is too thin for correct invocation: it omits parameter semantics, has no output schema, and gives no route to sibling memory operations. Even though the tool is conceptually simple, an agent needs more context about kind/sensitivity and when to store versus correct or forget.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description has the full burden of explaining statement, kind, and sensitivity, but mentions none of them. An agent cannot infer what values to supply for kind and sensitivity from this text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific action ('Store') and resource ('confirmed local memory'), clearly distinguishing it from retrieval tools like memory_search and deletion tools like forget. The phrase 'calling client is recorded as actor' further pins down what this tool does. It loses the fifth point because it does not explicitly name sibling alternatives or define what 'confirmed' means.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Aside from implying that the memory should be 'confirmed' and 'local', there is no guidance on when to choose this tool over memory_correct, memory_feedback, or forget. No explicit when-to-use, when-not-to-use, or alternative routing is provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reminder_setA
Schedule a Telegram reminder; chat_id must already be locally paired to receive it.
Alfred's only delivery channel today is Telegram, so the caller must
say which paired chat this goes to -- there is no channel-agnostic
queue to defer that choice to. When Hermes is answering an inbound
Telegram turn, chat_id may be omitted and is read from
ALFRED_TELEGRAM_CHAT_ID.
daily repeats at the same local wall-clock time (wake-up, bedtime,
study lock-in). When daily is true, timezone must be an IANA
name such as America/New_York so the hour survives a daylight-saving
change.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | ||
| daily | No | ||
| run_at | Yes | ||
| chat_id | No | ||
| task_id | No | ||
| timezone | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses important behavior beyond the annotations: reminders are delivered only via Telegram, chat_id must already be paired, and daily reminders follow wall-clock time with an IANA timezone for DST safety. Annotations are all false, so the description carries this burden and does it reasonably well, though it does not mention cancellation, deduplication, or persistence behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is moderately sized and front-loaded with the primary action and core prerequisite. Each paragraph addresses a distinct concern (delivery context, chat_id fallback, daily/timezone semantics) without significant filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the main Telegram-specific complexities and the daily/timezone interaction, which are the non-obvious parts. However, with no output schema and no description of run_at format or task_id, an agent still has meaningful gaps to resolve before calling it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description adds meaning for chat_id, daily, and timezone, but leaves the required run_at format and the purpose of task_id unexplained. This is partial compensation rather than full coverage of the parameter space.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource, 'Schedule a Telegram reminder', and adds a key prerequisite about a locally paired chat_id. It is clear but does not explicitly differentiate from sibling scheduling tools like task_schedule or nag_until_done.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides clear context for when chat_id is required versus when it can be read from ALFRED_TELEGRAM_CHAT_ID during an inbound Telegram turn, and explains the daily/timezone constraint. It stops short of naming alternatives or stating when not to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
system_statusARead-only
Return Alfred's non-sensitive local health and schema status.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnlyHint annotation already declares this as a read-only operation, and the description adds meaningful context by specifying 'non-sensitive', 'local', and 'schema status'. This helps an agent understand the data scope without contradicting the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, tightly scoped sentence with no filler. Every qualifier ('non-sensitive', 'local', 'health and schema status') contributes directly to tool understanding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter status tool with readOnlyHint and an output schema, the description is complete. It identifies what is returned and the scope, and the output schema can define the actual return structure without burdening the description.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the schema description coverage of 100% is vacuous. With no parameters to document, the baseline of 4 applies and the description does not need to add parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Return') and clearly identifies the resource: Alfred's non-sensitive local health and schema status. The qualifiers 'local' and 'non-sensitive' distinguish it from sibling status tools like composio_status and connector_status.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this tool versus alternatives. While the 'local' qualifier implies it is for Alfred's own status rather than external connectors, no explicit comparison or exclusion is provided for sibling status tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
task_completeAIdempotent
Mark an open task completed; completing an already-completed task is a no-op.
| Name | Required | Description | Default |
|---|---|---|---|
| task_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare idempotentHint=true, and the description repeats that behavior with 'completing an already-completed task is a no-op.' It does not add much beyond the annotation, though it does clarify the 'open task' precondition. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence with zero filler. It states the core action and the only edge case in compact form.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter tool with annotations covering idempotency, the description is nearly sufficient. It lacks explicit return behavior or failure details, but those are less critical given the tool's simplicity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has a single task_id property with 0% description coverage. The tool description does not explain what task_id refers to, how to obtain it, or any format expectations, so the description does not compensate for the schema's lack of parameter guidance.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'Mark an open task completed.' It clearly identifies the action and scope, and the no-op qualifier distinguishes this from task creation/scheduling tools like task_upsert or task_schedule.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context: use this when an open task should be marked completed. It does not explicitly name alternatives or when-not-to-use conditions, but the context is straightforward enough for selection among siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
task_scheduleA
Run an instruction later and send the answer to a paired chat.
Use this, not a reminder, when the user wants something done at a time rather than something said: "check the order at 3 and text me" has no message to deliver yet, because the answer does not exist until the work runs. A reminder would just hand the task back to them.
When it comes due the instruction is queued as an ordinary agent turn, so the reply arrives looking exactly like any other answer. Never schedule this kind of work in your own runtime's cron: Alfred owns schedules and delivery here, and a job elsewhere silently never fires.
run_at is ISO-8601 with an offset. daily repeats it, and then
timezone must be an IANA name (America/New_York) so the task keeps
its local hour across a daylight-saving change. When Hermes is
answering an inbound Telegram turn, chat_id may be omitted and is
read from ALFRED_TELEGRAM_CHAT_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| daily | No | ||
| prompt | Yes | ||
| run_at | Yes | ||
| chat_id | No | ||
| timezone | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only say it's not read-only and not destructive. The description goes far beyond: it explains that the instruction is queued as an ordinary agent turn ('the reply arrives looking exactly like any other answer'), warns that a job elsewhere silently never fires, and details the chat_id fallback behavior from ALFRED_TELEGRAM_CHAT_ID. It also clarifies daily/timezone handling. This is rich behavioral context not present in the schema or annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Though longer than typical, every sentence earns its place. The core action is stated first, then the critical distinction from reminders, then behavior, then parameter notes. No fluff or redundancy; the structure front-loads the most decision-relevant information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is complete for a scheduling tool: it covers what it does, when to use it, how the execution works, parameter formats, special cases (Telegram chat_id fallback), and a critical operational warning. No output schema exists, but that is not needed for a fire-and-forget scheduling action. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must explain parameters. It does well for the non-obvious ones: run_at must be ISO-8601 with offset, daily repeats it and then timezone must be IANA, chat_id may be omitted under a specific condition. It does not explicitly state that prompt is the instruction to run, but that is inferable from the tool's purpose and description. It adds significant meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear verb–resource pair: 'Run an instruction later and send the answer to a paired chat.' It immediately distinguishes itself from the sibling reminder_set by explaining when to use scheduling over a reminder ('when the user wants something *done* at a time rather than something *said*'), and gives a concrete example. This makes it impossible for an agent to confuse it with other tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use guidance ('Use this, not a reminder...'), a concrete example, and a strong when-not-to-use instruction ('Never schedule this kind of work in your own runtime's cron'). It also explains the alternative (a reminder) and why it would be inappropriate, leaving no ambiguity about selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
task_upsertA
Create a task, or update an existing one's title/due date when task_id is given.
Decision 8 classifies this as automatic and reversible, unlike deletion, so it needs no approval step.
| Name | Required | Description | Default |
|---|---|---|---|
| title | Yes | ||
| due_at | No | ||
| task_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The second sentence adds behavioral context beyond annotations by stating the operation is automatic, reversible, and requires no approval. It also clarifies that updates only affect title and due date, which is useful for the agent. This does not contradict the readOnlyHint, destructiveHint, or idempotentHint annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is brief and front-loads the core behavior in the first sentence. However, the 'Decision 8' reference is cryptic and unexplained, making the second sentence less useful than it could be.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the essential create/update logic and the role of task_id, which is enough for basic invocation. Yet it omits return-value expectations, error behavior, and any guidance on how task_id should be obtained; the unexplained 'Decision 8' reference also leaves a gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description compensates partly by explaining that task_id selects update mode and that title and due date are the fields manipulated. It does not explain due_at's ISO format or the meaning of null/omitted due_at, leaving the agent to rely on the schema for those details.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool creates a task or updates an existing task's title/due date when task_id is provided. It names the specific resource and action, though it does not explicitly distinguish itself from sibling tools like task_complete or task_schedule.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives internal routing guidance: create when task_id is absent, update when task_id is present. However, it does not explain when to choose this tool over alternatives or when not to use it, leaving sibling selection implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
threads_awaiting_replyARead-only
List unread Gmail threads that look like they need a reply.
Groups active unread mail by thread_id and drops messages that carry a
List-Unsubscribe header (newsletters Gmail often labels PERSONAL).
Run alfred gmail-thread-backfill once if older rows are missing
thread_id / list_unsubscribe.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true, and the description is consistent. The description adds valuable behavioral detail beyond the annotation: it groups by thread_id, drops messages carrying List-Unsubscribe headers, and warns that older rows may lack thread_id/list_unsubscribe unless a backfill is run. This gives the agent a realistic picture of data completeness and filtering behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no filler: the main action is front-loaded, the second sentence explains the core filtering logic, and the third is a compact operational note about the backfill command. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given there are no parameters and an output schema exists, the description fully covers what an agent needs to decide whether to call the tool and what to expect: source, unread/active filter, newsletter exclusion, and a data-quality caveat. Nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has no parameters, so there are no call arguments to document and schema coverage is effectively 100%. The description mentions internal fields like thread_id and list_unsubscribe, but those are implementation details rather than invocation parameters, so the baseline score for zero parameters applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('List'), a clear resource ('unread Gmail threads'), and the intended outcome ('that look like they need a reply'). The second sentence sharpens this by explaining that it groups by thread_id and drops List-Unsubscribe-bearing newsletters, making the tool's niche unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear operational context: the tool is for triaging active unread threads that plausibly need a reply, and explicitly excludes newsletter-style List-Unsubscribe messages. It also gives a concrete data prerequisite with the backfill command. It does not name alternatives or state explicit when-not-to-use cases, but no sibling tool appears to cover this same niche.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
33 tool updates
v0.2.0- First observed
action_commit - First observed
agenda_get - First observed
availability_get - First observed
brief_get - First observed
calendar_event_propose - First observed
composio_connect - First observed
composio_execute - First observed
composio_search - First observed
composio_status - First observed
connector_records_get - First observed
connector_status - First observed
forget - First observed
github_issue_propose - First observed
gratitude_record - First observed
important_date_set - First observed
important_dates_get - First observed
journal_get - First observed
memory_correct - First observed
memory_feedback - First observed
memory_search - First observed
message_draft - First observed
message_send_propose - First observed
mood_record - First observed
nag_until_done - First observed
profile_get - First observed
pull_requests_get - First observed
remember - First observed
reminder_set - First observed
system_status - First observed
task_complete - First observed
task_schedule - First observed
task_upsert - First observed
threads_awaiting_reply
TDQS
Scored across 33 tools
Most tools target a distinct action (search vs remember vs correct; propose vs commit; status vs records). The reminder family (reminder_set, nag_until_done, important_date_set, task_schedule) and status tools (system_status vs connector_status) create mild boundary overlap, but detailed descriptions make selection feasible.
Naming conventions are mixed: many tools are noun_verb (important_dates_get, connector_records_get), while others are verb_noun (task_complete, calendar_event_propose), bare verbs (remember, forget), or noun-only (system_status, connector_status). This inconsistency makes the surface harder to predict.
33 tools is above the 25+ threshold and feels heavy even for a multi-domain personal assistant. Several clusters (reminders, memory, status) could be consolidated without losing function.
Core lifecycles exist for memory, tasks, journaling, and composio, but calendar has create-only (no update/cancel), GitHub is limited to issue creation and PR listing, and task deletion is absent. Agents can complete common workflows but will hit gaps on updates and cancellations.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Private-by-default, local-first memory/context/task orchestrator for MCP apps and agents.
Persistent, portable memory for AI assistants — your private memory graph, from any MCP client.
Agent-native notes, tasks, dev-docs, vaults, sync & handoffs. MCP + OpenAPI dual surface.
One memory, every AI. A shared, user-owned markdown memory your AI clients read and write over MCP.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceA local-first AI secretary that gathers your work context into private memory and enables AI agents to search and summarize it over MCP.38MIT
- FlicenseNot gradedqualityDmaintenanceA privacy-first, local-first MCP server that provides 15 ADHD/second-brain tools for capturing, prioritizing, and resurfacing tasks with context from calendar, mail, and messages.1-
- AlicenseAqualityBmaintenanceA local-first, privacy-first MCP server that passively indexes personal digital activity (screenshots, clipboard, notes, downloads, links) into a local database, enabling LLMs like Claude to access your context without cloud storage.4MIT
- AlicenseNot gradedqualityAmaintenanceA self-hosted MCP server that provides any LLM with a graph-backed memory layer of your life—tasks, email, finance, contacts, calendar—plus autonomous agent offices that act on your behalf.1Apache 2.0