Applicable Scenarios
✅ Suitable for using this skill:
- Query my to-do tasks, tasks due today/this week, overdue tasks
- Create, update, archive tasks
- Update task status, priority, assignee, remarks
- Manage task progress, comments (supports @mentions), activities
- Upload files to tasks
- Query project list, project details
- Query enterprise members
- Manage sprints (create/start/complete)
❌ Not applicable scenarios:
- Operating on non-Teambition platforms (Jira, Asana, etc.)
- Git operations or code management → directly use
git - Manage Teambition organization/administrator settings not covered by the scripts
Environment Preparation
Get User Token:Teambition UserToken self-service application
# 方式 1:环境变量
export TEAMBITION_USER_TOKEN="your_token"
# 方式 2:在 dingtalk-teambition/ 目录下创建 user-token.json
# {"userToken": "your_token"}
cd dingtalk-teambition && uv sync
Core Rules
-
me(): When querying "my" tasks/projects in TQL, you must useexecutorId = me(), hardcoding user IDs is prohibited -
Time Zone:
create_task.py/update_task.py/manage_sprint.pyhas built-in UTC+8→UTC conversion, just pass local time directly; do not manually pass UTC time (it will be converted again causing deviation). Conversion logic reference:from datetime import datetime, timedelta user_date = "2026-03-15" dt = datetime.strptime(user_date, "%Y-%m-%d") - timedelta(hours=8) iso_date = dt.strftime("%Y-%m-%dT%H:%M:%S.000Z") # 结果:2026-03-14T16:00:00.000Z -
ID→Name: The various ID fields returned by the API are all raw ID strings,they must be converted to readable names before being shown to the user, directly displaying raw IDs is prohibited。
- Common ID fields that need conversion:
Field Meaning Conversion Method executorIdAssignee query_members.py --user-ids <ID>batch querycreatorIdCreator query_members.py --user-ids <ID>batch queryinvolveMembersParticipant list query_members.py --user-ids <ID1,ID2,...>batch querysprintIdSprint query_project_detail.py <projectId>get the sprint list and then matchstageIdTask column task details usually contain stageName, otherwise you need to query the project workflowprojectIdProject the project name is usually already in the context, or use query_project_detail.pyto queryparentTaskIdParent Task query_task_detail.py <parentTaskId>get the parent task title - Necessary steps when displaying task lists/details:
- Collect all kinds of IDs appearing in all tasks (deduplicate)
- Batch query the corresponding names (use
query_members.pyfor people, use the respective query scripts for projects/sprints/tasks) - Replace IDs with names before displaying to the user
- If the name corresponding to an ID cannot be determined, it can be displayed as "unknown" or the field can be kept but not displayed, do not directly display the raw ID
# 按姓名搜索成员,获取 userId uv run scripts/query_members.py --keyword "张三" # 返回结果中匹配 userId,确认后用于展示或操作 # 批量按用户ID查询成员(推荐用于ID转换) uv run scripts/query_members.py --user-ids "id1,id2,id3" - Common ID fields that need conversion:
-
Priority: The numeric meanings are
0=紧急 1=高 2=中 3=低, butenterprises usually customize priority names, the script output'spriorityLabelis only the system default value and does not represent the enterprise's actual configuration.- Before displaying priority names you must first query the enterprise configuration, query chain:
- Get from task details
projectId uv run scripts/query_project_detail.py <projectId> --extra-fields organizationIdgetorganizationIduv run scripts/get_priority_list.py <organizationId>get the enterprise's actual priority list
- Get from task details
- Each priority in the returned result contains
priority(numeric value) andname(enterprise-defined name), which override the default label before display - Before updating a priority, you also need to query first, match the priority name described by the user with the enterprise configuration, and then use the corresponding
prioritynumeric value to call the update API
- Before displaying priority names you must first query the enterprise configuration, query chain:
-
Archive vs Delete: Archiving a task moves it to the recycle bin and it will not be displayed in the normal list; it can be restored via
--restore; archiving is not the same as deletion -
Activity vs Progress: Activity is the operation history automatically recorded by the system (status changes, field modifications, etc.); progress (trace) is the stage-based status update manually filled in by the user
-
Iteration operation order: First use
--action create --project-id <id> --name <名>to create an iteration and obtain the sprint-id, then use--action start --project-id <id> --sprint-id <id>to start it, and after completion use--action complete --project-id <id> --sprint-id <id>; both start/complete require passing--project-idand--sprint-id -
Status query first: When updating a task status, prioritize using
get_task_statuses.py <taskId>to directly query the workflow status list of that task, without needing to obtain projectId first; only use it when creating a task and an initial status is neededget_taskflow_statuses.py -
Read documentation on demand: TQL syntax →
references/tql.md; progress/comments/activity/archive →references/task-ops.md; error handling →references/error-handling.md -
Create comment with file: Use
create_comment.py --file-paths <路径>to directly upload and attach files to a comment, supporting multiple files (comma-separated) -
ID link rendering: When a task ID or project ID is involved in a reply, it must be rendered as a clickable link in the following format:
- Task link:
https://www.teambition.com/task/{taskId} - Project link:
https://www.teambition.com/project/{projectId}
- Task link:
-
Task content = title: The
contentfield returned by the API is the task'stitle, and when displaying it to the user, uniformly use "title" rather than "content" to avoid confusion;create_task.pyandupdate_task.pyboth uniformly use the--titleparameter -
Hide empty fields: When displaying task or project information,fields whose values are empty, null, 0, false, or an empty array should be hidden and not shown to the user, and only fields with actual values should be displayed. For example:
- Progress is 0 → do not display progress
- Due date is null → do not display due date
- Notes are an empty string → do not display notes
- Iteration is null → do not display iteration
- Tags are an empty array → do not display tags
- This rule applies to all optional fields to keep information display concise
-
Custom field update format: When using
--customfieldsto update task custom fields, different types have different formats:# 日期类型(date):value 是数组,包含带 title 的对象,日期格式为 ISO 8601 uv run scripts/update_task.py --task-id 'xxx' \ --customfields '[{"customfieldId": "字段ID", "value": [{"title": "2026-03-16T00:00:00.000Z"}]}]' # 文本类型(text):value 是数组,包含带 title 的对象 uv run scripts/update_task.py --task-id 'xxx' \ --customfields '[{"customfieldId": "字段ID", "value": [{"title": "文本内容"}]}]' # 单选类型(select):value 是数组,包含带 id 的选项对象 uv run scripts/update_task.py --task-id 'xxx' \ --customfields '[{"customfieldId": "字段ID", "value": [{"id": "选项ID"}]}]' -
File-type custom field upload: Use
upload_file_to_customfield.py --file-pathsto upload one or more files to a custom field in one step:# 上传单个文件 uv run scripts/upload_file_to_customfield.py \ --task-id '<taskId>' \ --file-paths '/path/to/file.pdf' \ --customfield-id '<字段ID>' # 上传多个文件(逗号分隔) uv run scripts/upload_file_to_customfield.py \ --task-id '<taskId>' \ --file-paths '/path/a.pdf,/path/b.png' \ --customfield-id '<字段ID>' -
Custom field file type display: In custom fields, the type is
workthe field (file attachment); when displaying, the filename must be rendered as a clickable download link, using the value in the field'sdownloadUrlfield as the link address, in the following format:- Display format:
[文件名](downloadUrl) - Example:
[材料.md](https://xxx.com/...) - If a field contains multiple files, render each file as a separate link
- It is forbidden to display only the filename without an accompanying link
- Display format:
-
Batch task table output: when the query returnsmultiple tasks(2 or more),display in table form by default, and the table columns should include: title, status, priority, assignee, due date. A single-row task is still displayed as a text paragraph to keep the information clear and easy to read.
-
Destructive operations require confirmation: before performingarchive task(
archive_task.py)、deleteand other irreversible or high-impact operations,you must first confirm with the user, showing the operation object (task title/ID) and operation type, and execute only after obtaining explicit consent. For example:- "Confirm archiving the task "Complete Requirements Document" (ID: xxx)? After archiving, it can be restored from the recycle bin."
- "Confirm deleting this comment? It cannot be restored after deletion."
-
Empty fields are not returned: when the API queries task details,custom fields with empty values will not be returned. If a file-type field has never been assigned a value,
customfieldsthe field will not be included in the array. To view all custom fields that can be filled in for a task, you need to:# 1. 从任务详情获取 sfcId(任务类型ID)和 projectId uv run scripts/query_task_detail.py <taskId> --detail-level detailed # 2. 查询该任务类型可用的所有自定义字段 uv run scripts/get_custom_fields.py <projectId> --sfc-id <sfcId>In the returned result, fields with type
workare file-type fields -
Task type awareness: when creating a task, automatically infer the task type based on keywords in the user's description,do not create a regular task by default:
- If the user says "requirement"/"function"/"feature" → use
--name 需求to search for matching task types - If the user says "defect"/"bug"/"issue" → use
--name 缺陷to search for matching task types - If the user says "task" or does not specify clearly → use
--name 任务to search, or use the project's default type - Operation process:
- After determining the projectId, first execute
uv run scripts/get_scenario_types.py <projectId> --name <关键词>to query matching task types - If a unique match is found, directly use its
idas the--scenariofieldconfig-idparameter - If multiple matches are found, choose the one whose name is closest to the user's intent
- If no match is found, do not pass
--scenariofieldconfig-id, and use the project's default type
- After determining the projectId, first execute
- If the user says "requirement"/"function"/"feature" → use
-
Intelligent project inference: when creating a task, if the user does not specify a project,do not choose a project randomly, and handle it according to the following process:
- Execute
uv run scripts/query_projects.py --tql "involveMembers = me()"to query the projects the user participates in - If there is only 1project, automatically use that project and inform the user
- If there are multipleproject, display the project list (name + ID), and ask the user which project to choose before creating
- Execute
Script Quick Reference
| Script | Purpose | Key Parameters |
|---|---|---|
query_tasks.py |
Query task list (TQL), returns by default: title, status, priority, assignee ID, due date, notes, sprint, task column, start time, progress, parent task ID | --tql <TQL> --page-size N --page-token T --no-details --extra-fields f1,f2 |
query_task_detail.py <id1,id2> |
Query task details (supports batch) | --detail-level simple|detailed --extra-fields f1,f2 |
create_task.py |
Create task | --title <标题>(required)--project-id --executor-id --due-date --priority |
update_task.py |
Update task (multiple fields in parallel) | --task-id <id>(required)--title --executor-id --due-date --note --priority --taskflowstatus-id |
update_task_priority.py |
Update priority separately (before updating, you must first use get_priority_list.py to query enterprise configuration) |
--task-id <id> --priority <0-3> |
create_comment.py |
Create comment (supports direct file upload) | --task-id <id> --content <内容> --mention <姓名> --mention-id <userId> --file-paths <路径> --file-tokens <token> |
query_projects.py |
Query project list (TQL) | --tql <TQL> --page-size N --page-token T --no-details --include-template |
query_project_detail.py <id> |
Query project details (supports batch) | --detail-level simple|detailed --extra-fields f1,f2 |
query_members.py |
Search members (supports batch ID query) | --keyword <姓名> --user-ids <ID1,ID2,...> |
get_task_statuses.py <taskId> |
Query task workflow status list (recommended) | --name <关键词> |
get_taskflow_statuses.py <projectId> |
Get project workflow status (used when creating tasks) | --only-start --name <关键词> |
get_custom_fields.py <projectId> |
Get project custom field configuration | --cf-ids <IDs> --sfc-id <ID> |
get_scenario_types.py <projectId> |
Get project task type list | --name <关键词> --sfc-ids <IDs> |
get_priority_list.py <organizationId> |
Get enterprise priority configuration | — |
get_current_user.py |
Get current logged-in user information (userId, name, email, etc.) | — |
create_trace.py |
Add task progress | --task-id <id> --title <标题> --status <1-3> |
upload_file_to_customfield.py |
Upload files to custom fields (supports multiple files) | --task-id <id> --file-paths <路径> --customfield-id <id> |
archive_task.py |
Archive/restore task | --task-id <id> [--restore] |
query_task_activity.py |
Query task activity | --task-id <id> --actions comment |
manage_sprint.py |
Sprint management | --action list|create|start|complete --project-id <id> --sprint-id <id> --name <名> |
query_task_detail.py parameter description
| Parameter | Type | Required | Description |
|---|---|---|---|
任务ID |
String | Yes | Task ID, comma-separated supports batch |
--detail-level |
String | No | simple(default) or detailed |
--extra-fields |
String | No | Additional fields to include in simple mode, comma-separated |
simple (default) includes fields:
| Field | Description |
|---|---|
id |
Task ID |
content |
Task title |
isDone |
Completed or not |
executorId |
Assignee ID |
projectId |
Project ID |
dueDate |
Due date |
priority |
Priority (0=Urgent, 1=High, 2=Medium, 3=Low) |
created |
Creation time |
updated |
Update time |
note |
Notes |
detailed additionally includes:sprintId(sprint ID)stageId(task column ID)startDate(start time)progress(progress)parentTaskId(parent task ID) and custom fields, etc., 30+ fields
query_project_detail.py parameter description
| Parameter | Type | Required | Description |
|---|---|---|---|
项目ID |
String | Yes | Project ID, comma-separated supports batch |
--detail-level |
String | No | simple(default) or detailed |
--extra-fields |
String | No | Additional fields to include in simple mode, comma-separated |
simple (default) Contains fields:
| Field | Description |
|---|---|
id |
Project ID |
name |
Project name |
description |
Project description |
visibility |
Visibility (public/private) |
isTemplate |
Whether it is a template project |
creatorId |
Creator ID |
isArchived |
Whether it is in the recycle bin |
isSuspended |
Whether it has been archived |
created |
Creation time |
updated |
Update time |
detailed Additionally contains:logo(Project LOGO)organizationId(Enterprise ID)uniqueIdPrefix(Task ID prefix)startDate(Start time)endDate(End time) and 20+ other fields
TQL Quick Reference
Common Task TQL Scenarios
| Scenario | TQL |
|---|---|
| My to-do tasks | executorId = me() AND isDone = false |
| My overdue tasks | executorId = me() AND isDone = false AND dueDate < startOf(d) |
| Tasks due today | executorId = me() AND dueDate >= startOf(d) AND dueDate <= endOf(d) |
| Tasks due this week | executorId = me() AND dueDate >= startOf(w) AND dueDate <= endOf(w) |
| Due soon (next 3 days) | executorId = me() AND isDone = false AND dueDate >= startOf(d) AND dueDate <= endOf(d, 3d) |
| Tasks updated in the past 7 days | executorId = me() AND updated >= startOf(d, -7d) |
| High priority incomplete | priority = 0 AND isDone = false |
| Title fuzzy search | title ~ '关键词' |
| Full-text search (title + notes) | text ~ '关键词' |
| Tasks in a specified project | projectId = 'xxx' |
Complete TQL syntax (fields, operators, time functions) →
references/tql.md
Common Project TQL Scenarios
| Scenario | TQL |
|---|---|
| Projects I participate in | involveMembers = me() |
| Projects I created | creatorId = me() |
| Search by name | nameText ~ '关键词' |
| Archived projects | isSuspended = true |
| Projects updated today | updated >= startOf(d) AND updated <= endOf(d) |
| Projects created today | created >= startOf(d) AND created <= endOf(d) |
| Projects created this week | created >= startOf(w) AND created <= endOf(w) |
| Projects created this month | created >= startOf(M) AND created <= endOf(M) |
| Projects created in the past 7 days | created >= startOf(d, -7d) |
| Created within a specified date range | created >= '2026-03-01T00:00:00.000Z' AND created <= '2026-03-31T23:59:59.999Z' |
⚠️ Projects do not have a due date (dueDate) field, only
createdandupdated。Complete project TQL →
references/project-tql.md
Common Command Examples
Query tasks
# 我的待办任务
uv run scripts/query_tasks.py --tql "executorId = me() AND isDone = false"
# 注意:返回的 executorId 是原始 ID,需批量调用 query_members.py --user-ids 转换为姓名后展示
# 我的逾期任务,按截止时间升序
uv run scripts/query_tasks.py --tql "executorId = me() AND isDone = false AND dueDate < startOf(d) ORDER BY dueDate ASC"
# 返回的 executorId 需批量转换为姓名:uv run scripts/query_members.py --user-ids "<id1,id2,...>"
# 本周截止的任务
uv run scripts/query_tasks.py --tql "executorId = me() AND dueDate >= startOf(w) AND dueDate <= endOf(w)"
# 标题搜索
uv run scripts/query_tasks.py --tql "title ~ '需求'"
# 查询任务详情(simple 默认,含 note)
uv run scripts/query_task_detail.py <taskId>
# 查询详细信息(含自定义字段等)
uv run scripts/query_task_detail.py <taskId> --detail-level detailed
# 批量查询多个任务
uv run scripts/query_task_detail.py id1,id2,id3
Create task
# 基本创建
uv run scripts/create_task.py --project-id 'xxx' --title '完成需求文档'
# 完整参数创建
uv run scripts/create_task.py \
--project-id 'xxx' \
--title '实现登录模块' \
--executor-id 'uid' \
--due-date '2026-04-01' \
--priority 1 \
--note '参考设计稿'
Update task
# 更新标题和优先级(多字段并行执行)
uv run scripts/update_task.py --task-id 'xxx' --title '新标题' --priority 0
# 更新截止日期和执行人
uv run scripts/update_task.py --task-id 'xxx' --due-date '2026-04-01' --executor-id 'uid'
# 更新任务状态(先查询状态 ID)
uv run scripts/get_task_statuses.py <taskId>
uv run scripts/update_task.py --task-id 'xxx' --taskflowstatus-id '状态ID'
# 单独更新优先级
uv run scripts/update_task_priority.py --task-id 'xxx' --priority 0
Query projects
# 我参与的项目
uv run scripts/query_projects.py --tql "involveMembers = me()"
# 按名称搜索
uv run scripts/query_projects.py --tql "nameText ~ '产品开发'"
# 查询项目详情
uv run scripts/query_project_detail.py <projectId>
# 获取 organizationId(用于查询优先级配置)
uv run scripts/query_project_detail.py <projectId> --extra-fields organizationId
Query members and current user
# 按姓名搜索成员
uv run scripts/query_members.py --keyword '张三'
# 批量按用户ID查询成员(推荐用于ID转换)
uv run scripts/query_members.py --user-ids "id1,id2,id3"
# 获取当前登录用户信息(userId、name、email 等)
uv run scripts/get_current_user.py
Create comment (with @mention)
# 创建评论并 @张三(--mention 接受姓名,脚本自动查询 userId)
uv run scripts/create_comment.py \
--task-id 'xxx' \
--content '请张三确认一下' \
--mention '张三'
# @多人(逗号分隔)
uv run scripts/create_comment.py \
--task-id 'xxx' \
--content '请张三和李四评审' \
--mention '张三,李四'
# 已知 userId 时可直接用 --mention-id
uv run scripts/create_comment.py \
--task-id 'xxx' \
--content '已更新' \
--mention-id '61cad8021deea2ac89a4cbf3'
Create comment with files
# 带单个文件创建评论(自动上传并附加)
uv run scripts/create_comment.py \
--task-id 'xxx' \
--content '附件请查收' \
--file-paths '/path/to/doc.pdf'
# 带多个文件创建评论(逗号分隔)
uv run scripts/create_comment.py \
--task-id 'xxx' \
--content '附件请查收' \
--file-paths '/path/a.pdf,/path/b.png'
# 同时使用文件路径和已有 token(混合使用)
uv run scripts/create_comment.py \
--task-id 'xxx' \
--content '附件请查收' \
--file-paths '/path/to/new.pdf' \
--file-tokens 'existing_token1,existing_token2'
Update file field with files
# 上传单个文件到自定义字段
uv run scripts/upload_file_to_customfield.py \
--task-id 'xxx' \
--file-paths '/path/to/document.pdf' \
--customfield-id 'yyy'
# 上传多个文件到自定义字段(逗号分隔)
uv run scripts/upload_file_to_customfield.py \
--task-id 'xxx' \
--file-paths '/path/a.pdf,/path/b.png,/path/c.docx' \
--customfield-id 'yyy'
Paginated query
query_tasks.py and query_projects.py both support pagination:
| Parameter | Description |
|---|---|
--page-size <N> |
Number of records per page (default determined by API) |
--page-token <T> |
Pass in the value returned last time nextPageToken to get the next page |
# 第一页
uv run scripts/query_tasks.py --tql "executorId = me()" --page-size 50
# 下一页(使用上次输出中的 nextPageToken)
uv run scripts/query_tasks.py --tql "executorId = me()" --page-size 50 --page-token "上次返回的TOKEN"