Skip to main content
Glama

penny_write

Save the moment something durable emerges — a decision, preference, plan, correction, a to-do, a measurement, or something you produced — mid-conversation and unprompted; when the call is close, save. Choose entityType: walk this ladder, first match wins:

  1. Durable fact about the user or their people → update the profile (profile upsert or penny_edit), not a note. How they want to be remembered → memory_policy, a general rule in their words; how they want you to show up (tone/register/manner) → persona. When the user tells you what to save, skip, check, or surface, update their memory_policy block in the same turn as a general rule in their words.

  2. Commitment/action with a done-state → task. Organize via area/project/heading. A to-do the user mentions, even in passing, is a task: offer to capture it, then write it. Project create: patch.name/purpose + operationId; revise: projectId + expectedRevision from Brief + sparse patch (max 25 step/resource changes). project_interaction records actor proposals/declines/deferrals. pending_share_approval is a proposal, not a save. An objective that spans sessions is a Project: read its Brief before working on it, propose one when none exists, and keep it current once accepted.

  3. Measurement → tracker_entry for an existing tracker (check inventory); otherwise propose tracker first. Active duplicate tracker names are rejected; edit with penny_edit. A measurement the user would log more than once is a tracker entry; if no tracker fits, propose one before logging.

  4. Reusable know-how → skill; trigger makes it scheduled (legacy rhythm). Existing skill names prepare a preview; wait for user approval before penny_edit op:apply with proposalId. Run on-demand via skill_invoke; begin scheduled runs via skill_run. Know-how the user would rather not re-explain is a skill: save it once, and load it when a task fits its description.

  5. Other context/events/ideas/learning → note. Prefer a specific type when unsure; a note is the fallback, not the default. When the user is learning something to keep, offer to let them try first; if search shows they asked before, say so once with the date; save misses and level. If so, read penny_get_skill references/learning.md. Also tag_relation and tracker_note_link. Batch notes or tracker_entry entries: max100. Modify existing items with penny_edit; trash with penny_delete. Reuse an existing tag before minting a new one. Tagging and linking conventions live in the Penny skill.

Note confidence measures signal, not pipeline: 0.95 = explicit user statement; 0.80 = confirmed decision; 0.60 = reasonable inference; 0.40 = hedged or sleeptime-derived; 0.20 = weak signal. Each note needs sampleQuestions: exactly three short, distinct natural-language questions derived from its content, in the user's voice, not keywords or near-duplicates. For an APA preference: ["What citation style should I use for the paper?", "How should I format references in my thesis?", "What’s my usual academic style?"].

Input Schema

NameRequiredDescriptionDefault
goalNorhythm: required run instructions; skill uses instructions instead.
kindNotracker: required; habit|metric|goal|log|status|custom.
nameNoRequired: tracker/area/project/rhythm and entityType:"skill". skill_invoke/skill_run: alternative to skillId. Existing skill names preview changes; new names create. Active tracker duplicates are rejected; archived names reactivate.
tagsNotask: tags to attach.
unitNotracker: unit of measure.
actorNotask/area/project/heading: actor (me|agent) recorded in activity ledger.
childNotag_relation: required child tag.
notesNonote: array (max 100), each requires content and confidence (0–1), plus tags and exactly 3 sampleQuestions in the user’s voice; optional source/memoryType (episodic|semantic|procedural)/validFrom. task/area/project: markdown string.
orderNotask/area/project/heading: sort order.
ownerNotask: assignee.
patchNoProject: sparse changes; omitted fields stay. Max 25 step/resource changes.
scopeNoProfile: global|workspace. Projects: private; workspace requires workspaceId.
titleNotask/heading: required title/label.
areaIdNoproject: required parent area.
parentNotag_relation: required parent tag of child_of edge.
sourceNonote/tracker_entry: provenance; defaults conversation/agent-mcp respectively.
statusNotask: initial status.
whenAtNotask/project: schedule date (ms epoch).
contentNoprofile: required block content.
deliverNoentityType:"skill": required with trigger; rhythm: required. Omit for on-demand. Scheduled output: {kind:'note',tags?:string[]}|{kind:'profile_block',blockName:string}|{kind:'notify'}.
entriesNotracker_entry: up to 100 for one trackerId; each {payload,loggedAt?,agentNote?,noteIds?,source?,metadata?,externalId?}. Mutually exclusive with top-level payload. Receipts list saved/failed items and duplicates for stored externalIds; do not claim all saved from a partial result.
noteIdsNotracker_entry: archival note IDs to attach. tracker_note_link: required note IDs to link.
payloadNotracker_entry: tracker-defined data point; required unless entries is used.
postureNoentityType:"skill" with trigger, or rhythm: read|propose|act; default read.
skillIdNoskill_invoke/skill_run: skill to run now/begin; required unless name is given.
triggerNoentityType:"skill": optional; rhythm: required. Requires deliver. Penny does not run it; due signals reach the connected agent. Schedule: {kind:"schedule",cadence:"daily"|"weekly"|"monthly",at?:"Fri 16:00",timezone?:"America/Denver"}. ALWAYS set IANA timezone; default UTC shifts local times. Event: {kind:"event",on:"note.created",where?:{tags?:string[]}}.
deadlineNotask/project: hard due date (ms epoch).
rhythmIdNorhythm_run: rhythm to begin; or pass name.
agentNoteNotracker_entry, single only: short non-searchable caption.
blockNameNoprofile: required block name to upsert.
dependsOnNotask: full prerequisite taskId set; replaces all.
headingIdNotask: parent heading.
linkNotesNotask: note IDs to link.
projectIdNotask: parent Project. heading: required parent Project.
reasoningNotag_relation: short edge justification, typically a user quote.
trackerIdNotracker_entry: required tracker to log against.
entityTypeYesWhat to create; first match in the tool description's ladder wins.
externalIdNotracker_entry, also entries items: source record ID, max 200 chars. Use for imports/sync: repeats on the same tracker return the existing entry as duplicate. Opaque, unencrypted: never include content.
recordedAtNotracker_entry, single only: observation time (ms epoch); default now.
recurrenceNotask: repeat. Returned taskId is the first occurrence; completion returns nextTaskId (see penny_edit status). Never reuse a completed occurrence's ID.
targetSpecNotracker: JSON target spec, interpreted at retrieval (e.g. {kind:'daily_minimum',value:10000}).
whenBucketNotask/project: undated bucket; mutually exclusive with whenAt.
descriptionNotracker: required meaning. entityType:"skill"/rhythm: required one-line purpose, including on-demand skills.
interactionNoproject_interaction: actor decision; read first, update with expectedUpdatedAt.
operationIdNoProject receipt key; identical retries only.
instructionsNoskill: required know-how for invocation or when a connected agent picks up a due skill. Replaces rhythm goal.
retrievalPlanNoentityType:"skill"/rhythm: optional deterministic steps [{tool,args}] for a bounded tier.
trackerEntryIdNotracker_note_link: required entry to attach notes to.
expectedRevisionNoProject revision from Brief; reconcile conflicts.
expectedUpdatedAtNoSource version from read.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed48 schema fields changed
    • changedInput schema / properties / actor / description
      Previous value: -"entityType:\"task\"/\"area\"/\"project\"/\"heading\" — who took the action (me|agent), written to the activity ledger."New value: +"task/area/project/heading: actor (me|agent) recorded in activity ledger."
    • changedInput schema / properties / agentNote / description
      Previous value: -"entityType:\"tracker_entry\" (single-entry form only) — short caption on this one data point (not searchable)."New value: +"tracker_entry, single only: short non-searchable caption."
    • changedInput schema / properties / areaId / description
      Previous value: -"entityType:\"project\" (required) — the area the project belongs to."New value: +"project: required parent area."
    • changedInput schema / properties / blockName / description
      Previous value: -"entityType:\"profile\" (required) — the profile block name to upsert."New value: +"profile: required block name to upsert."
    • changedInput schema / properties / child / description
      Previous value: -"entityType:\"tag_relation\" (required) — the child tag."New value: +"tag_relation: required child tag."
    • changedInput schema / properties / content / description
      Previous value: -"entityType:\"profile\" (required) — the block content."New value: +"profile: required block content."
    • changedInput schema / properties / deadline / description
      Previous value: -"entityType:\"task\"/\"project\" — hard due date (ms epoch)."New value: +"task/project: hard due date (ms epoch)."
    • changedInput schema / properties / deliver / description
      Previous value: -"entityType:\"skill\" — REQUIRED once `trigger` is set (and on the legacy entityType:\"rhythm\"); omit on an on-demand skill. Where a scheduled run's output lands: { kind:'note', tags?:string[] } | { kind:'profile_block', blockName:string } | { kind:'notify' }."New value: +"entityType:\"skill\": required with trigger; rhythm: required. Omit for on-demand. Scheduled output: {kind:'note',tags?:string[]}|{kind:'profile_block',blockName:string}|{kind:'notify'}."
    • changedInput schema / properties / dependsOn / description
      Previous value: -"entityType:\"task\" — full replacement set of taskIds that must complete first."New value: +"task: full prerequisite taskId set; replaces all."
    • changedInput schema / properties / description / description
      Previous value: -"entityType:\"tracker\" (required) — natural-language meaning. entityType:\"skill\" (required — every skill, on-demand or scheduled) or legacy \"rhythm\" — one-line description of what it is for."New value: +"tracker: required meaning. entityType:\"skill\"/rhythm: required one-line purpose, including on-demand skills."
    • changedInput schema / properties / entityType / description
      Previous value: -"What to create. Walk the ladder in the tool description; first match wins."New value: +"What to create; first match in the tool description's ladder wins."
    • changedInput schema / properties / entries / description
      Previous value: -"tracker_entry: batch up to 100 entries for one trackerId; each {payload,loggedAt?,agentNote?,noteIds?,source?,metadata?}. Mutually exclusive with top-level payload. Receipts report each saved/failed item; do not claim all saved from a partial result."New value: +"tracker_entry: up to 100 for one trackerId; each {payload,loggedAt?,agentNote?,noteIds?,source?,metadata?,externalId?}. Mutually exclusive with top-level payload. Receipts list saved/failed items and duplicates for stored externalIds; do not claim all saved from a partial result."
    • changedInput schema / properties / expectedRevision / description
      Previous value: -"Project edit revision from Brief; reconcile conflicts."New value: +"Project revision from Brief; reconcile conflicts."
    • changedInput schema / properties / expectedUpdatedAt / description
      Previous value: -"Source version from the read."New value: +"Source version from read."
    • addedInput schema / properties / externalId
      Added value: +{
      +  "description": "tracker_entry, also entries items: source record ID, max 200 chars. Use for imports/sync: repeats on the same tracker return the existing entry as duplicate. Opaque, unencrypted: never include content.",
      +  "type": "string"
      +}
    • changedInput schema / properties / goal / description
      Previous value: -"entityType:\"rhythm\" (required) — natural-language instruction: what the run should do. On entityType:\"skill\" this is `instructions`."New value: +"rhythm: required run instructions; skill uses instructions instead."
    • changedInput schema / properties / headingId / description
      Previous value: -"entityType:\"task\" — heading to file the task under."New value: +"task: parent heading."
    • changedInput schema / properties / instructions / description
      Previous value: -"entityType:\"skill\" (required) — the saved know-how: what to do when the skill is invoked, or when a connected agent picks it up after it comes due. Generalizes the rhythm \"goal\"."New value: +"skill: required know-how for invocation or when a connected agent picks up a due skill. Replaces rhythm goal."
    • changedInput schema / properties / kind / description
      Previous value: -"entityType:\"tracker\" (required) — habit | metric | goal | log | status | custom."New value: +"tracker: required; habit|metric|goal|log|status|custom."
    • changedInput schema / properties / linkNotes / description
      Previous value: -"entityType:\"task\" — note ids to link to this task."New value: +"task: note IDs to link."
    • changedInput schema / properties / name / description
      Previous value: -"Required for tracker/area/project and entityType:\"skill\" (also rhythm); for skill_invoke/skill_run, an alternative to skillId. Existing skill names prepare a change preview; new names create. Active tracker duplicates are rejected; archived names reactivate."New value: +"Required: tracker/area/project/rhythm and entityType:\"skill\". skill_invoke/skill_run: alternative to skillId. Existing skill names preview changes; new names create. Active tracker duplicates are rejected; archived names reactivate."
    • changedInput schema / properties / noteIds / description
      Previous value: -"entityType:\"tracker_entry\" — archival note ids to attach; or \"tracker_note_link\" (required) — the notes to link."New value: +"tracker_entry: archival note IDs to attach. tracker_note_link: required note IDs to link."
    • changedInput schema / properties / order / description
      Previous value: -"entityType:\"task\"/\"area\"/\"project\"/\"heading\" — sort order."New value: +"task/area/project/heading: sort order."
    • changedInput schema / properties / owner / description
      Previous value: -"entityType:\"task\" — assignee."New value: +"task: assignee."
    • changedInput schema / properties / parent / description
      Previous value: -"entityType:\"tag_relation\" (required) — the parent tag in the child_of edge."New value: +"tag_relation: required parent tag of child_of edge."
    • changedInput schema / properties / patch / description
      Previous value: -"Project sparse changes; omitted fields stay. Max 25 step/resource changes."New value: +"Project: sparse changes; omitted fields stay. Max 25 step/resource changes."
    • changedInput schema / properties / patch / properties / steps / description
      Previous value: -"accept converts a saved suggestion into a To-do."New value: +"accept turns a saved suggestion into a To-do."
    • changedInput schema / properties / payload / description
      Previous value: -"entityType:\"tracker_entry\" (required unless `entries` is used) — the structured data point; shape is tracker-defined."New value: +"tracker_entry: tracker-defined data point; required unless entries is used."
    • changedInput schema / properties / posture / description
      Previous value: -"entityType:\"skill\" with a `trigger` set (or legacy \"rhythm\") — read | propose | act (defaults 'read')."New value: +"entityType:\"skill\" with trigger, or rhythm: read|propose|act; default read."
    • changedInput schema / properties / projectId / description
      Previous value: -"entityType:\"task\" — parent project; or \"heading\" — the project it belongs to (required)."New value: +"task: parent Project. heading: required parent Project."
    • changedInput schema / properties / reasoning / description
      Previous value: -"entityType:\"tag_relation\" — short justification (typically a user quote) for the edge."New value: +"tag_relation: short edge justification, typically a user quote."
    • changedInput schema / properties / recordedAt / description
      Previous value: -"entityType:\"tracker_entry\" (single-entry form only) — observation time (ms epoch; defaults to now)."New value: +"tracker_entry, single only: observation time (ms epoch); default now."
    • changedInput schema / properties / recurrence / description
      Previous value: -"entityType:\"task\" — makes the task repeat. The returned `taskId` is this task's first occurrence; completing it later returns `nextTaskId` for the next one (see penny_edit's `status` field) — don't cache this id past its first completion."New value: +"task: repeat. Returned taskId is the first occurrence; completion returns nextTaskId (see penny_edit status). Never reuse a completed occurrence's ID."
    • changedInput schema / properties / recurrence / properties / at / description
      Previous value: -"Time expression: \"HH:MM\" for daily, \"<Wd> HH:MM\" for weekly, \"DD HH:MM\" for monthly."New value: +"daily: HH:MM; weekly: <Wd> HH:MM; monthly: DD HH:MM."
    • changedInput schema / properties / retrievalPlan / description
      Previous value: -"entityType:\"skill\" (or legacy \"rhythm\") — OPTIONAL deterministic steps [{ tool, args }] for a bounded tier."New value: +"entityType:\"skill\"/rhythm: optional deterministic steps [{tool,args}] for a bounded tier."
    • changedInput schema / properties / rhythmId / description
      Previous value: -"entityType:\"rhythm_run\" — the rhythm to begin a run of (or pass `name`)."New value: +"rhythm_run: rhythm to begin; or pass name."
    • changedInput schema / properties / skillId / description
      Previous value: -"entityType:\"skill_invoke\" (required, or pass `name`) — the skill to run now. entityType:\"skill_run\" — the skill to begin a run of (or pass `name`)."New value: +"skill_invoke/skill_run: skill to run now/begin; required unless name is given."
    • changedInput schema / properties / source / description
      Previous value: -"entityType:\"note\"/\"tracker_entry\" — provenance label (defaults 'conversation' / 'agent-mcp')."New value: +"note/tracker_entry: provenance; defaults conversation/agent-mcp respectively."
    • changedInput schema / properties / status / description
      Previous value: -"entityType:\"task\" — initial status."New value: +"task: initial status."
    • changedInput schema / properties / tags / description
      Previous value: -"entityType:\"task\" — tags to attach."New value: +"task: tags to attach."
    • changedInput schema / properties / targetSpec / description
      Previous value: -"entityType:\"tracker\" — JSON target spec, interpreted at retrieval (e.g. { kind: 'daily_minimum', value: 10000 })."New value: +"tracker: JSON target spec, interpreted at retrieval (e.g. {kind:'daily_minimum',value:10000})."
    • changedInput schema / properties / title / description
      Previous value: -"entityType:\"task\" (required) or \"heading\" (required) — the title/label."New value: +"task/heading: required title/label."
    • changedInput schema / properties / trackerEntryId / description
      Previous value: -"entityType:\"tracker_note_link\" (required) — the logged tracker entry to attach notes to."New value: +"tracker_note_link: required entry to attach notes to."
    • changedInput schema / properties / trackerId / description
      Previous value: -"entityType:\"tracker_entry\" (required) — the tracker to log against."New value: +"tracker_entry: required tracker to log against."
    • changedInput schema / properties / trigger / description
      Previous value: -"entityType:\"skill\": optional schedule (required for rhythm), requires deliver. Penny does not run it: due signals reach the connected agent. Schedule: {kind:\"schedule\",cadence:\"daily\"|\"weekly\"|\"monthly\",at?:\"Fri 16:00\",timezone?:\"America/Denver\"}. ALWAYS set timezone (IANA); default UTC shifts local times. Event: {kind:\"event\",on:\"note.created\",where?:{tags?:string[]}}."New value: +"entityType:\"skill\": optional; rhythm: required. Requires deliver. Penny does not run it; due signals reach the connected agent. Schedule: {kind:\"schedule\",cadence:\"daily\"|\"weekly\"|\"monthly\",at?:\"Fri 16:00\",timezone?:\"America/Denver\"}. ALWAYS set IANA timezone; default UTC shifts local times. Event: {kind:\"event\",on:\"note.created\",where?:{tags?:string[]}}."
    • changedInput schema / properties / unit / description
      Previous value: -"entityType:\"tracker\" — unit of measure."New value: +"tracker: unit of measure."
    • changedInput schema / properties / whenAt / description
      Previous value: -"entityType:\"task\"/\"project\" — schedule date (ms epoch)."New value: +"task/project: schedule date (ms epoch)."
    • changedInput schema / properties / whenBucket / description
      Previous value: -"entityType:\"task\"/\"project\" — undated bucket; mutually exclusive with whenAt."New value: +"task/project: undated bucket; mutually exclusive with whenAt."
  2. Changed1 schema field changed
    • changedInput schema / properties / trigger / description
      Previous value: -"entityType:\"skill\": optional schedule (required for rhythm), requires deliver. MyPenny does not run it: due signals reach the connected agent. Schedule: {kind:\"schedule\",cadence:\"daily\"|\"weekly\"|\"monthly\",at?:\"Fri 16:00\",timezone?:\"America/Denver\"}. ALWAYS set timezone (IANA); default UTC shifts local times. Event: {kind:\"event\",on:\"note.created\",where?:{tags?:string[]}}."New value: +"entityType:\"skill\": optional schedule (required for rhythm), requires deliver. Penny does not run it: due signals reach the connected agent. Schedule: {kind:\"schedule\",cadence:\"daily\"|\"weekly\"|\"monthly\",at?:\"Fri 16:00\",timezone?:\"America/Denver\"}. ALWAYS set timezone (IANA); default UTC shifts local times. Event: {kind:\"event\",on:\"note.created\",where?:{tags?:string[]}}."
  3. First observed

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish that this is a write tool, but the description adds substantial behavioral context: batch limits of 100, duplicate handling, tracker receipts, skill preview/approval flow, task recurrence return behavior, project revision conflicts, and confidence scoring semantics. These are concrete operational traits beyond 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.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded and uses a numbered ladder for structure, but it is very dense, includes duplicated schema detail, and contains long run-on clauses. The complexity justifies some length, but several details could be tightened without losing invocation guidance.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given a 50-parameter omnibus tool with no output schema, the description covers the major workflows, constraints, and return-relevant behaviors such as duplicates and task recurrence. It still does not fully explain return behavior or every entity type, but schema coverage and annotations make it sufficiently complete for invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents parameters extensively. The description adds crucial meaning beyond the schema by providing the entityType selection ladder and mapping each entity type to the relevant workflow and parameters, though it does not add semantics for all 50 parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific action—save durable information mid-conversation—and defines the resource scope through an explicit entityType ladder. It also distinguishes the tool from siblings by naming penny_edit for modifications, penny_delete for trashing, and other alternatives for profiles, trackers, skills, and notes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives extensive when-to-use guidance: save when something durable emerges and the call is close, follow the first-match entityType ladder, prefer specific types over notes, check tracker inventory, propose trackers when missing, and use penny_edit or penny_delete instead of penny_write for modifications/removals. It also names exceptions such as pending_share_approval being a proposal, not a save.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources