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:
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.
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.
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.
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.
Other context/events/ideas/learning → note. Prefer a specific type when unsure; a note is the fallback, not the default. 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
| Name | Required | Description | Default |
|---|---|---|---|
| goal | No | rhythm: required run instructions; skill uses instructions instead. | |
| kind | No | tracker: required; habit|metric|goal|log|status|custom. | |
| name | No | 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. | |
| tags | No | task: tags to attach. | |
| unit | No | tracker: unit of measure. | |
| actor | No | task/area/project/heading: actor (me|agent) recorded in activity ledger. | |
| child | No | tag_relation: required child tag. | |
| notes | No | note: 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. | |
| order | No | task/area/project/heading: sort order. | |
| owner | No | task: assignee. | |
| patch | No | Project: sparse changes; omitted fields stay. Max 25 step/resource changes. | |
| scope | No | Profile: global|workspace. Projects: private; workspace requires workspaceId. | |
| title | No | task/heading: required title/label. | |
| areaId | No | project: required parent area. | |
| parent | No | tag_relation: required parent tag of child_of edge. | |
| source | No | note/tracker_entry: provenance; defaults conversation/agent-mcp respectively. | |
| status | No | task: initial status. | |
| whenAt | No | task/project: schedule date (ms epoch). | |
| content | No | profile: required block content. | |
| deliver | No | entityType:"skill": required with trigger; rhythm: required. Omit for on-demand. Scheduled output: {kind:'note',tags?:string[]}|{kind:'profile_block',blockName:string}|{kind:'notify'}. | |
| entries | No | 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. | |
| noteIds | No | tracker_entry: archival note IDs to attach. tracker_note_link: required note IDs to link. | |
| payload | No | tracker_entry: tracker-defined data point; required unless entries is used. | |
| posture | No | entityType:"skill" with trigger, or rhythm: read|propose|act; default read. | |
| skillId | No | skill_invoke/skill_run: skill to run now/begin; required unless name is given. | |
| trigger | No | 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[]}}. | |
| deadline | No | task/project: hard due date (ms epoch). | |
| rhythmId | No | rhythm_run: rhythm to begin; or pass name. | |
| agentNote | No | tracker_entry, single only: short non-searchable caption. | |
| blockName | No | profile: required block name to upsert. | |
| dependsOn | No | task: full prerequisite taskId set; replaces all. | |
| headingId | No | task: parent heading. | |
| linkNotes | No | task: note IDs to link. | |
| projectId | No | task: parent Project. heading: required parent Project. | |
| reasoning | No | tag_relation: short edge justification, typically a user quote. | |
| trackerId | No | tracker_entry: required tracker to log against. | |
| entityType | Yes | What to create; first match in the tool description's ladder wins. | |
| externalId | No | 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. | |
| recordedAt | No | tracker_entry, single only: observation time (ms epoch); default now. | |
| recurrence | No | task: repeat. Returned taskId is the first occurrence; completion returns nextTaskId (see penny_edit status). Never reuse a completed occurrence's ID. | |
| targetSpec | No | tracker: JSON target spec, interpreted at retrieval (e.g. {kind:'daily_minimum',value:10000}). | |
| whenBucket | No | task/project: undated bucket; mutually exclusive with whenAt. | |
| description | No | tracker: required meaning. entityType:"skill"/rhythm: required one-line purpose, including on-demand skills. | |
| interaction | No | project_interaction: actor decision; read first, update with expectedUpdatedAt. | |
| operationId | No | Project receipt key; identical retries only. | |
| instructions | No | skill: required know-how for invocation or when a connected agent picks up a due skill. Replaces rhythm goal. | |
| retrievalPlan | No | entityType:"skill"/rhythm: optional deterministic steps [{tool,args}] for a bounded tier. | |
| trackerEntryId | No | tracker_note_link: required entry to attach notes to. | |
| expectedRevision | No | Project revision from Brief; reconcile conflicts. | |
| expectedUpdatedAt | No | Source version from read. |