ima技能安装步骤


ima技能安装步骤

![[Pasted image 20260323110439.png]]

安装指引

第1步:复制提示词,发给小龙虾以部署ima skill

请安装 ima 技能 下载地址:https://app-dl.ima.qq.com/skills/ima-skills-1.0.5.zip API Key 获取:https://ima.qq.com/agent-interface

第2步:获取API Key,发给小龙虾以完成配置

ima-note

通过 IMA OpenAPI 管理用户个人笔记,支持读取(搜索、列表、获取内容)和写入(新建、追加)。

完整的数据结构和接口参数详见 references/api.md

Setup

  1. 请打开 https://ima.qq.com/agent-interface 获取 Client IDApi Key
  2. 配置环境变量:
export IMA_OPENAPI_CLIENTID="your_client_id"
export IMA_OPENAPI_APIKEY="your_api_key"

建议将上述 export 语句写入 ~/.zshrc~/.bashrc,避免每次重开终端失效。

凭证预检

每次调用 API 前,先确认凭证可用。如果环境变量未设置,停止操作并提示用户按 Setup 步骤配置。

if [ -z "$IMA_OPENAPI_CLIENTID" ] || [ -z "$IMA_OPENAPI_APIKEY" ]; then
  echo "缺少 IMA 凭证,请按 Setup 步骤配置环境变量 IMA_OPENAPI_CLIENTID 和 IMA_OPENAPI_APIKEY"
  exit 1
fi

API 调用模板

所有请求统一为 HTTP POST + JSON Body,Base URL 为 https://ima.qq.com/openapi/note/v1

定义辅助函数避免重复 header:

ima_api() {
  local endpoint="$1" body="$2"
  curl -s -X POST "https://ima.qq.com/openapi/note/v1/$endpoint" \
    -H "ima-openapi-clientid: $IMA_OPENAPI_CLIENTID" \
    -H "ima-openapi-apikey: $IMA_OPENAPI_APIKEY" \
    -H "Content-Type: application/json" \
    -d "$body"
}

隐私规则: 笔记内容属于用户隐私,在群聊场景中只展示标题和摘要,禁止展示笔记正文。

接口决策表

用户意图 调用接口 关键参数
搜索/查找笔记 search_note_book query_info(QueryInfo 对象)
查看笔记本列表 list_note_folder_by_cursor cursor(必填,首页传"0") + limit(必填)
浏览某笔记本里的笔记,当用户表述"最新"、"最近"之类的通用限定,没有指明笔记本时,都应该直接在全部笔记里去拉 list_note_by_folder_id folder_id(选填,空为全部笔记本) + cursor(必填,首次传"") + limit(必填)
读取笔记正文 get_doc_content doc_id + target_content_format(必填,推荐0纯文本)
新建一篇笔记 import_doc content + content_format(必填,固定1) + 可选 folder_id⚠️ 必须先做 UTF-8 校验
往已有笔记追加内容 append_doc doc_id + content + content_format(必填,固定1)。⚠️ 必须先做 UTF-8 校验

常用工作流

查找并阅读笔记

先搜索获取 docid,再用 get_doc_content 读取正文:

# 1. 按标题搜索
ima_api "search_note_book" '{"search_type": 0, "query_info": {"title": "会议纪要"}, "start": 0, "end": 20}'
# 从返回的 docs[].doc.basic_info.docid 中取目标笔记 ID

# 2. 读取正文(纯文本格式,Markdown 格式目前不支持)
ima_api "get_doc_content" '{"doc_id": "目标docid", "target_content_format": 0}'

浏览笔记本里的笔记

先拉笔记本列表获取 folder_id,再拉该笔记本下的笔记:

# 1. 列出笔记本(首页 cursor 传 "0")
ima_api "list_note_folder_by_cursor" '{"cursor": "0", "limit": 20}'

# 2. 拉取指定笔记本的笔记(首页 cursor 传 "")
ima_api "list_note_by_folder_id" '{"folder_id": "user_list_xxx", "cursor": "", "limit": 20}'

新建笔记

⚠️ 写入前必须完成 UTF-8 编码校验,详见「⚠️ UTF-8 编码强制要求」章节。跳过此步骤会导致笔记乱码。

# 新建到默认位置
ima_api "import_doc" '{"content_format": 1, "content": "# 标题\n\n正文内容"}'

# 新建到指定笔记本
ima_api "import_doc" '{"content_format": 1, "content": "# 标题\n\n正文内容", "folder_id": "笔记本ID"}'
# 返回 doc_id,后续可用于 append_doc

追加内容到已有笔记

⚠️ 写入前必须完成 UTF-8 编码校验,详见「⚠️ UTF-8 编码强制要求」章节。跳过此步骤会导致笔记乱码。

ima_api "append_doc" '{"doc_id": "笔记ID", "content_format": 1, "content": "\n## 补充内容\n\n追加的文本"}'

按正文搜索

ima_api "search_note_book" '{"search_type": 1, "query_info": {"content": "项目排期"}, "start": 0, "end": 20}'

核心响应字段

搜索结果SearchedDoc):笔记信息路径为 doc.basic_info(DocBasic),关键字段:docidtitlesummaryfolder_idfolder_namecreate_time(Unix 毫秒)、modify_timestatus。额外包含 highlight_info(高亮匹配,key 为 doc_title,value 含 <em>高亮词</em>)。

笔记本条目NoteBookFolder):信息路径为 folder.basic_info(NoteBookFolderBasic),关键字段:folder_idnamenote_numbercreate_timemodify_timefolder_type0=用户自建,1=全部笔记,2=未分类)、status

笔记列表条目NoteBookInfo):信息路径为 basic_info.basic_info(DocBasicInfo → DocBasic),关键字段:docidtitlesummaryfolder_idfolder_namecreate_timemodify_timestatus

写入结果import_doc/append_doc):返回 doc_id(新建或目标笔记的唯一 ID)。

完整字段定义见 references/api.md

分页

  • 游标分页 — 笔记本列表list_note_folder_by_cursor):首次 cursor: "0",后续用 next_cursoris_end=true 时停止。
  • 游标分页 — 笔记列表list_note_by_folder_id):首次 cursor: "",后续用 next_cursoris_end=true 时停止。
  • 偏移量分页search_note_book):首次 start: 0, end: 20,翻页时递增,is_end=true 时停止。

枚举值

  • content_format 0=纯文本,1=Markdown,2=JSON。写入(import_doc/append_doc)目前仅支持 1(Markdown)。读取(get_doc_content)推荐 0(纯文本),Markdown 格式不支持。
  • search_type 0=标题检索(默认),1=正文检索
  • sort_type 0=更新时间(默认),1=创建时间,2=标题,3=大小(仅 search_note_book 使用)
  • folder_type 0=用户自建,1=全部笔记(根目录),2=未分类

注意事项

  • folder_id 不可为 "0",根目录 ID 格式为 user_list_{userid}(从 folder_type=1 的笔记本条目获取)
  • 笔记内容有大小上限,超过时返回 100009,可拆分为多次 append_doc 写入
  • 展示笔记列表时只展示标题、摘要和修改时间,不要主动展示正文
  • 时间字段是 Unix 毫秒时间戳,展示时转为可读格式
  • 返回数据为嵌套结构:搜索结果取 docs[].doc.basic_info.docid,笔记本取 note_book_folders[].folder.basic_info.folder_id,笔记列表取 note_book_list[].basic_info.basic_info.docid,注意按层级解析
  • UTF-8 编码:见下方「⚠️ UTF-8 编码强制要求」章节。

⚠️ UTF-8 编码强制要求(CRITICAL)

此规则为强制性要求,不可跳过。 非法编码会导致笔记在 IMA 中显示为乱码,且无法修复,必须重新写入。

每次调用 import_docappend_doc 之前,必须对 contenttitle 等所有字符串字段执行 UTF-8 编码校验/转换。 无论内容来源如何——用户直接输入、从文件读取、WebFetch 抓取、剪贴板粘贴、外部 API 返回——都不能假设已经是合法 UTF-8,必须显式确认。

强制检查清单

在构造 import_doc / append_doc 的请求 body 之前,完成以下步骤:

  1. 来自文件的内容:先检测文件编码,转为 UTF-8 后再读入变量
  2. 来自 WebFetch / HTTP 请求的内容:响应可能为 GBK/Latin-1 等,必须转码
  3. 来自用户输入或变量拼接的内容:清洗非法 UTF-8 字节(\xff\xfe 等)
  4. 标题字段同理title 也必须为合法 UTF-8
  5. 检测运行环境:如果当前 shell 是 PowerShell,必须检测版本(见下方「PowerShell 5.1 环境检测」),PowerShell 5.1 需要特殊处理否则所有写入都会静默乱码

各环境转码方法

Python(推荐,几乎所有环境都有):

# 读取文件,自动检测编码并转为 UTF-8
content=$(python3 -c "
import sys
data = open('tmpfile', 'rb').read()
for enc in ['utf-8', 'gbk', 'gb2312', 'big5', 'latin-1']:
    try:
        sys.stdout.write(data.decode(enc))
        break
    except (UnicodeDecodeError, LookupError):
        continue
" 2>/dev/null)

# 如果内容已在变量中,清洗非法 UTF-8 字节
content=$(printf '%s' "$content" | python3 -c "import sys; sys.stdout.write(sys.stdin.buffer.read().decode('utf-8','ignore'))")

Node.js:

content=$(node -e "const fs=require('fs');const buf=fs.readFileSync('tmpfile');process.stdout.write(buf.toString('utf8'))")
# 已知编码(如 GBK):
content=$(node -e "const fs=require('fs');process.stdout.write(new TextDecoder('gbk').decode(fs.readFileSync('tmpfile')))")

Unix (macOS/Linux):

content=$(iconv -f "$(file -b --mime-encoding tmpfile)" -t UTF-8 tmpfile 2>/dev/null || cat tmpfile)

Windows PowerShell:

# 读取非 UTF-8 文件并转码
$content = [System.IO.File]::ReadAllText('tmpfile', [System.Text.Encoding]::Default)
[System.IO.File]::WriteAllText('tmpfile.utf8', $content, [System.Text.Encoding]::UTF8)

⚠️ PowerShell 5.1 环境检测(CRITICAL)

此问题极其隐蔽:PowerShell 5.1 下 Invoke-RestMethod 会静默将请求 Body 从 UTF-8 转为系统 ANSI 编码(中文 Windows 为 GBK),即使设置了 Content-Type: charset=utf-8 也无效。结果是笔记内容看起来写入成功,但在 IMA 中显示为乱码,且无任何错误提示。

当 agent 运行在 PowerShell 环境时,必须在首次写入前检测版本:

# 检测 PowerShell 版本 — 在任何 import_doc / append_doc 之前执行
if ($PSVersionTable.PSVersion.Major -le 5) {
    Write-Host "⚠️ 检测到 PowerShell 5.1,将使用 UTF-8 字节数组模式发送请求"
    $useUtf8Bytes = $true
} else {
    Write-Host "✅ PowerShell 7+,默认 UTF-8,无需额外处理"
    $useUtf8Bytes = $false
}

PowerShell 5.1 下必须使用以下方式发送写入请求(用 ConvertTo-Json 构建 JSON 以避免手动拼接的转义风险,再显式转为 UTF-8 字节数组):

# PowerShell 5.1 安全写入模板
$body = @{ title = "标题"; content = $content; content_format = 1 } | ConvertTo-Json -Depth 10
if ($useUtf8Bytes) {
    # CRITICAL: 必须转为字节数组,否则中文/非ASCII内容会变成乱码
    $utf8Bytes = [System.Text.Encoding]::UTF8.GetBytes($body)
    Invoke-RestMethod -Uri $url -Method Post -Body $utf8Bytes -ContentType "application/json; charset=utf-8" -Headers $headers
} else {
    # PowerShell 7+ 可直接传字符串
    Invoke-RestMethod -Uri $url -Method Post -Body $body -ContentType "application/json; charset=utf-8" -Headers $headers
}

总结: 在 PowerShell 环境中,不检测版本直接发请求 = 中文笔记必乱码。这是 PowerShell 5.1 的已知设计缺陷,不是 bug 可以被修复。

错误处理

错误码 含义 建议处理
0 成功
100001 参数错误 检查请求参数格式和必填字段
100002 无效 ID 检查凭证配置
100003 服务器内部错误 等待后重试
100004 size 不合法 / 空间不够 检查参数范围
100005 无权限 确认操作的是用户自己的笔记
100006 笔记已删除 告知用户该笔记不存在
100008 版本冲突 重新获取内容后再操作
100009 超过大小限制 拆分为多次 append_doc 写入
310001 笔记本不存在 检查 folder_id 是否正确
20002 apiKey超过最大限频
20004 apikey 鉴权失败 检查凭证配置是否正确
110037 apikey 过期 请获取最新apikey:https://ima.qq.com/agent-interface

IMA笔记 API

⚠️ 必读约束

🔒 认证

所有请求必须携带 Header:

ima-openapi-clientid: {IMA_OPENAPI_CLIENTID}
ima-openapi-apikey: {IMA_OPENAPI_APIKEY}
Content-Type: application/json

🔒 安全规则

  • 笔记属于用户隐私,不要在群聊中主动展示笔记内容
  • 仅响应授权用户的笔记操作请求。

快速决策

用户意图 接口别名
「搜索笔记」「找包含XX的笔记」 /openapi/note/v1/search_note_book
「列出笔记本」「有哪些笔记本」 /openapi/note/v1/list_note_folder_by_cursor
「查看XX笔记本里的笔记」 /openapi/note/v1/list_note_by_folder_id
「从markdown新建笔记」「导入笔记」 /openapi/note/v1/import_doc
「追加内容到笔记」「在笔记末尾添加」 /openapi/note/v1/append_doc
「获取笔记纯文本」「读取笔记内容」 /openapi/note/v1/get_doc_content

数据结构


DocBasicInfo

字段 类型 说明
basic_info DocBasic DocBasic

DocBasic

字段 类型 说明
docid string 文章 id
title string 标题
summary string 简介
create_time int64
modify_time int64
status DocStatus 文章状态,0=正常,1=已删除
folder_id string 文件夹 id
folder_name string 文件夹名称
summary_style map<string, string> 简介样式

FolderItem(笔记本条目)

list_note_folder_by_cursor 返回的笔记本对象,字段如下:

字段 类型 说明
folder_id string 笔记本唯一 ID
name string 笔记本名称
note_number int64 笔记本内笔记数量
create_time int64 创建时间(Unix 毫秒)
modify_time int64 修改时间(Unix 毫秒)
parent_folder_id string 上级笔记本 ID(支持嵌套)
folder_type int 类型:0=用户自建,1=全部笔记,2=未分类
status int 状态:0=正常,1=已删除

QueryInfo

字段 类型 说明
title string 标题 query
content string 正文 query

SearchedDoc

字段 类型 说明
doc DocBasicInfo 笔记 basic 数据,见 DocBasicInfo
highlight_info map<string, string> 该条笔记匹配的高亮词,key: doc_title(文档标题),value: 包含 <em>高亮词</em> 的字段值

NoteBookFolder

字段 类型 说明
folder NoteBookFolderBasicInfo 笔记本信息,非笔记本为空,见 NoteBookFolderBasicInfo

NoteBookFolderBasicInfo

字段 类型 说明
basic_info NoteBookFolderBasic NoteBookFolderBasic

NoteBookFolderBasic

字段 类型 说明
folder_id string 文件夹 id
name string 笔记本名称
status DocStatus 笔记本状态,0=正常,1=已删除
create_time int64 创建时间
modify_time int64 修改时间
note_number int64 笔记数量
folder_type FolderType 文件夹类型:0=用户自建,1=全部笔记,2=未分类

NoteBookInfo

字段 类型 说明
basic_info DocBasicInfo 笔记基础信息,见 DocBasicInfo

接口详情

1. 搜索笔记

POST /openapi/note/v1/search_note_book

触发场景:用户说「搜索」「找笔记」「查找包含XX的内容」

请求参数

字段 类型 必填 说明
search_type SearchType 检索方式,默认为标题,0=标题,1=正文
sort_type SortType 排序方式,默认为更新时间,0=更新时间,1=创建时间,2=标题,3=大小
query_info QueryInfo 用户 query,见 QueryInfo
start int64 翻页字段,起始编号
end int64 翻页字段,终止编号,与start相差不超过20
query_id string queryid

返回字段

字段 类型 说明
docs SearchedDoc[] 检索到的笔记 list,见 SearchedDoc
is_end bool 是否为最后一批数据
total_hit_num int64 检索命中结果总数

2. 列出笔记本

POST /openapi/note/v1/list_note_folder_by_cursor

触发场景:用户说「列出笔记本」「有哪些分类」「查看笔记本目录」

请求参数

字段 类型 必填 说明
cursor string 游标,第一页传 "0",后续传后台返回的值
limit uint64 获取笔记数量限制,不要超过20

返回字段

字段 类型 说明
note_book_folders NoteBookFolder[] NoteBookFolder
next_cursor string 下次请求的起始游标
is_end bool 是否为最后一批数据

3. 按笔记本拉取笔记列表

POST /openapi/note/v1/list_note_by_folder_id

触发场景:用户说「查看XX笔记本的笔记」「列出这个笔记本里的内容」

全部笔记根目录的 folder_iduser_list_{userid},可从「列出笔记本」返回的 folder_id 获取。

请求参数

字段 类型 必填 说明
folder_id string 笔记本 ID,根目录为空
cursor string 当前游标,首次传空字符串 ""
limit uint64 获取笔记数量限制,不要超过20

返回字段

字段 类型 说明
note_book_list NoteBookInfo[] NoteBookInfo
next_cursor string 下次请求的起始游标
is_end bool 是否为最后一批数据

4. 从 Markdown 新建笔记

POST /openapi/note/v1/import_doc

触发场景:用户说「从 Markdown 新建笔记」「导入笔记」「把这段 Markdown 保存为笔记」

请求参数

字段 类型 必填 说明
content_format int 文本类型:1=Markdown(默认)目前仅支持 MARKDOWN(值为 1
content string 笔记正文内容, 只支持markdown格式, 不要传空值
folder_id string 关联的笔记本id

返回字段

字段 类型 说明
doc_id string 新doc的唯一ID

5. 追加内容到笔记

POST /openapi/note/v1/append_doc

触发场景:用户说「在这篇笔记末尾追加内容」「把 XX 添加到笔记里」

请求参数

字段 类型 必填 说明
doc_id string 目标笔记的唯一ID, 需要是本人的笔记
content_format int 文本类型:1=Markdown(默认)目前仅支持 MARKDOWN(值为 1
content string 要追加的文本内容, 只支持markdown格式

返回字段

字段 类型 说明
doc_id string 目标笔记的唯一ID

6. 获取笔记纯文本

POST /openapi/note/v1/get_doc_content

触发场景:用户说「读取笔记内容」「获取这篇笔记的纯文本」「把笔记转成 Markdown」

请求参数

字段 类型 必填 说明
doc_id string 目标笔记的唯一 ID, 需要是本人的笔记
target_content_format int 目标文本类型:0=纯文本(推荐),1=Markdown(不支持),2=JSON

返回字段

字段 类型 说明
content string 笔记的文本内容(按 target_content_format 格式返回)

枚举值

sort_type(排序方式)

说明
0 更新时间(默认)
1 创建时间
2 标题
3 大小

search_type(检索方式)

说明
0 标题检索(默认)
1 正文检索

content_format(文本类型)

说明
0 PLAINTEXT - 纯文本
1 MARKDOWN - Markdown 格式
2 JSON - JSON 格式

FolderType

说明
0 用户自建
1 全部笔记
2 未分类

游标翻页使用规范

  1. 首次请求cursor 传空字符串 ""
  2. 检查返回的 is_endfalse 表示还有更多数据
  3. 将返回的 next_cursor 作为下次请求的 cursor
  4. is_end = true 时停止翻页

错误码

错误码 说明
0 成功
100001 参数错误
100002 携带无效的 ID
100003 服务器内部错误
100004 拉取的 size 不合法(超出范围)/ 用户空间不够
100005 不能获取私有笔记的访客信息 / 不是笔记的作者
100006 笔记已被删除
100008 版本冲突
100009 单篇笔记超过最大限制
310001 笔记本不存在
20002 apiKey超过最大限频
20004 apikey鉴权失败
110037 apikey 过期

文章作者: 摸鱼
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 摸鱼 !
  目录