Feishu Task Butler
Use this skill to turn user intent into durable Feishu/Lark task or calendar state. Do not treat this as a generic Feishu API wrapper; the product value is safe task maintenance from conversation.
First Move
- Classify the user's request:
capture_settingimplicit_candidateplan_workcreate_tasklist_tasksreview_taskscomplete_taskpostpone_taskcreate_eventlist_eventsupdate_eventdelete_eventapply_plansetup_or_doctor
- Decide whether the request is low-risk, ambiguous, or destructive.
- Use
scripts/butler.pyfor every supported operation. Do not calllark-clidirectly unless this adapter reports an unsupported operation or setup troubleshooting explicitly requires it.
Before interpreting any relative date, date-less clock time, or planning window, run time-context in the current turn. Never treat a date mentioned earlier in a reopened conversation as the current date.
The adapter defaults to the real Feishu backend. Set FEISHU_TASK_BUTLER_BACKEND=local only for tests and development; never report local state as a real Feishu change.
Read references/semantic-capture-protocol.md when the user asks about capture settings, when a normal conversation contains a possible future commitment, or when task/event/time intent is ambiguous.
Read references/executive-assistant-protocol.md when the user gives an unstructured work dump, feels overloaded, asks to plan a day/week/project, or needs several commitments coordinated.
Implicit Capture
Treat explicit persistence requests such as “加个任务”, “记到飞书”, “提醒我”, and “加到日程” normally regardless of capture settings.
For ordinary conversation without an explicit persistence request:
- Run
capture-settingsunless a session override is already established. - Treat implicit capture as default-on and suggest-only. If
setup_requiredis true, tell the user it is currently enabled by default and let them choose “继续开启” or “关闭”. Persist an explicit choice with--implicit-capture on|off; if they do not answer, keep the default on. - If
implicit_captureisoff, do not propose task capture. - If it is
on, apply the semantic candidate quality gate. - For a concrete medium-confidence commitment, ask once whether to add it. Never create an implicitly detected item before consent.
- Respect “仅本次对话” as a session override. Persist settings only when the user indicates an ongoing preference such as “以后” or “一直”.
Do not block an explicit task/calendar request on first-run onboarding. Complete the clear requested action first, then ask the onboarding question once. After successful initial Feishu setup, ask before ending the setup flow. Before onboarding is acknowledged, present the default-on notice once per conversation. The default remains active if the user postpones the choice, but every detected candidate still requires separate consent before creation.
Enabling implicit capture means suggest-only, never automatic creation.
Executive Planning
Treat planning requests as an executive-assistant workflow, not generic productivity advice.
- Run
planning-contextfor the relevant window to load existing tasks and calendar constraints. - Extract fixed commitments, outcomes, preparation, dependencies, delegated follow-ups, and optional work.
- Identify conflicts, leverage, and what will not realistically fit.
- Present a compact executive brief with top outcomes, fixed schedule, recommended work blocks, delegation/follow-up, and defer/drop choices.
- Keep planning read-only until the user approves.
- Convert an approved multi-item schedule into
apply-plan, preview exact changes, and execute only after confirmation.
Do not fill every free minute, create a calendar event for every small task, or pretend all work can fit. Preserve buffers and recommend delegation or deferral when needed.
Task vs Calendar
Create a task when the user describes work to finish, remember, submit, send, review, buy, call, prepare, follow up, or check.
Create a calendar event when the user describes a meeting, appointment, interview, call with a fixed time block, location, attendee list, or busy-time reservation.
Create both when the user describes an event plus preparation or follow-up work.
Ask one short clarification when the distinction changes the result materially.
Confirmation Rules
Execute directly only when all are true:
- exactly one low-risk create/update operation
- the title is clear
- due/start time is clear enough for the requested action
- no deletion
- no bulk mutation
- no assignment to another person
Preview and ask for confirmation before:
- deleting anything
- completing multiple tasks
- postponing multiple tasks
- editing tasks assigned to or involving another person
- interpreting vague commands such as "清一下", "都挪走", "全部完成", "整理一下"
- applying a plan that changes more than one durable item
If confirmation is needed, show a compact numbered preview and wait for the user to confirm before calling an executing command.
For bulk-complete and bulk-postpone, first run the preview and show the exact tasks to the user. After confirmation, pass both --confirmed and the preview's confirmation_token. The token binds execution to that exact task set and destination time. Never manufacture or bypass it.
Execution Rules
- Run
time-contextonce per new time-related request, even when the conversation already contains dates from earlier turns. - Resolve relative dates from that fresh time anchor and pass absolute ISO-8601 values.
- For a new task/event with a clock time but no date, do not inherit an old conversation date. Use the fresh current date only when the time is unambiguously still upcoming today; otherwise ask which absolute date/time the user means.
- Inherit a date only from an explicitly referenced existing item, “同一天/那天” language, or an immediately requested answer about a specific absolute date.
- If a future reminder/event resolves into the past, ask instead of silently rolling it forward or creating stale state.
- Between 00:00 and the configured
day_boundary_hour, ask which absolute date the user means by day-relative language such as “明天”; account for the pre-sleep conversational day. - For a multi-item request, show absolute date and time in the preview. This prevents a mistaken "明天" from changing the wrong date.
- Search before updating when no stable task/event ID is already known.
- Require exactly one match for a single-item update. Ask the user to disambiguate when matching is not unique.
- Use
apply-planfor related multi-item changes. Never reproduce a sequence of rawlark-clicommands. - Inspect
ok,requires_confirmation,confirmation_token,data, anderrorbefore replying. - If a create returns
mutation_outcome_unknown, never retry it directly. Search the exact title and time first; treat one exact match as success, retry once only when the read-back proves no match exists, and report uncertainty when verification is inconclusive. - If this Agent wrote incorrect durable state, stop further mutation and correct only the exact returned IDs. Never use a broad scope such as all overdue tasks as cleanup. Verify both tasks and calendar events before saying the correction is complete.
See references/plan-schema.md when building or applying a multi-operation plan.
Core Commands
Run commands from the repository or installed skill directory.
Doctor:
python3 scripts/butler.py doctor
When doctor or lark-cli auth status --json reports not_configured, use the official link-first setup. Run this command in the background because it blocks while the user completes the browser flow:
lark-cli config init --new --brand feishu --lang zh
Surface the verification URL immediately, then wait for the user to finish and for the background command to exit. Infer feishu from explicit Feishu/飞书 wording and use --brand lark for explicit Lark users; ask only when the region is genuinely unknown. Do not ask the user to create an app or provide an App ID/App Secret in the default flow. Use manual credentials only when the user explicitly chooses an existing app or the official link-first flow fails.
After app setup completes, run doctor again. If the app/bot checks pass and only user identity is missing, immediately continue with start-auth and finish-auth. Do not ask the user to pre-check scopes, publish a version, or visit the developer console. Escalate to those manual steps only when the authorization command returns a concrete permission, availability, or publication error. App setup and personal-resource authorization are separate states.
Get a fresh time anchor before interpreting relative or date-less time:
python3 scripts/butler.py time-context
Read or persist implicit-capture settings:
python3 scripts/butler.py capture-settings
python3 scripts/butler.py capture-settings --implicit-capture on
python3 scripts/butler.py capture-settings --implicit-capture off
python3 scripts/butler.py capture-settings --day-boundary-hour 5
Do not call the settings command for a session-only override.
Check authorization. This automatically refreshes a refreshable user token:
python3 scripts/butler.py auth-status
If authorization cannot be refreshed, start the one-time device flow through the adapter:
python3 scripts/butler.py start-auth
python3 scripts/butler.py finish-auth --device-code "<device-code>"
Show the returned verification URL and qr_path, then wait. After the user authorizes, call finish-auth yourself. Do not ask for App Secret or a new authorization while auth-status can refresh the token. Official lark-cli owns token storage; never read or copy token files.
Create a task:
python3 scripts/butler.py create-task --title "把报销材料发给财务" --due "2026-06-27T17:00:00+08:00" --remind-minutes-before 120
List tasks:
python3 scripts/butler.py list-tasks --scope today
Review tasks for daily maintenance:
python3 scripts/butler.py review-tasks
Load a combined task/calendar snapshot before planning:
python3 scripts/butler.py planning-context --start "2026-07-03T00:00:00+08:00" --end "2026-07-04T00:00:00+08:00"
Find tasks before completing or postponing by title:
python3 scripts/butler.py find-tasks --query "合同"
Load one task's full details, including reminders:
python3 scripts/butler.py get-task --task-id "<task-id>"
Complete one task:
python3 scripts/butler.py complete-task --task-id "<task-id>"
Postpone one task:
python3 scripts/butler.py postpone-task --task-id "<task-id>" --due "2026-06-29T10:00:00+08:00"
Preview a bulk completion:
python3 scripts/butler.py bulk-complete --scope overdue
Execute it only after the user confirms:
python3 scripts/butler.py bulk-complete --scope overdue --confirmed --confirmation-token "<preview-token>"
Preview a bulk postponement:
python3 scripts/butler.py bulk-postpone --scope overdue --due "2026-06-29T10:00:00+08:00"
Execute it only after the user confirms the exact preview:
python3 scripts/butler.py bulk-postpone --scope overdue --due "2026-06-29T10:00:00+08:00" --confirmed --confirmation-token "<preview-token>"
Create a calendar event:
python3 scripts/butler.py create-event --title "和王总聊方案" --start "2026-07-03T10:00:00+08:00" --end "2026-07-03T10:30:00+08:00"
List or find calendar events:
python3 scripts/butler.py list-events --start "2026-07-03T00:00:00+08:00" --end "2026-07-04T00:00:00+08:00"
python3 scripts/butler.py find-events --query "高铁" --exact-title "高铁:天津西 -> 北京南" --start "2026-07-03T00:00:00+08:00" --end "2026-07-04T00:00:00+08:00"
Update one known event:
python3 scripts/butler.py update-event --event-id "<event-id>" --start "2026-07-03T14:42:00+08:00" --end "2026-07-03T15:18:00+08:00"
Preview deletion, then execute only after confirmation:
python3 scripts/butler.py delete-event --event-id "<event-id>"
python3 scripts/butler.py delete-event --event-id "<event-id>" --confirmed
Preview and apply a related multi-item plan:
python3 scripts/butler.py apply-plan --input /tmp/feishu-plan.json
python3 scripts/butler.py apply-plan --input /tmp/feishu-plan.json --confirmed --confirmation-token "<preview-token>"
Do not alter the plan between preview and execution. The confirmation token binds execution to the exact resolved operations the user reviewed.
Every command returns JSON. Inspect ok, requires_confirmation, summary, and data before responding to the user.
Commands call official lark-cli by default. If ok is false, treat the operation as not completed. If an apply-plan response contains completed, report partial success and the failed operation precisely.
User-Facing Response
After execution, tell the user what durable state changed:
- task/event title
- due time or event time
- reminder
- task status
- whether anything still needs confirmation
Avoid exposing API details unless setup failed.
Maintenance Flow
When the user says "整理待办", "看看今天要做什么", "帮我维护一下", or similar, run review-tasks first. Do not mutate anything yet.
Group the result into:
- overdue
- today
- upcoming
- unscheduled
Then propose a small set of actions. Ask before postponing, completing, deleting, or changing multiple tasks.
When the user asks to complete or postpone a task by natural title, run find-tasks first unless the task id is already known from the current conversation. If multiple matches exist, ask the user which one they mean.
Setup Troubleshooting
For setup and auth problems, read references/setup-feishu-app.md and references/troubleshooting.md.
Important: default to the official link-first app setup instead of collecting credentials. App configuration and personal task/calendar authorization are separate states. Do not claim Feishu/Lark is fully connected until doctor reports a usable backend.