Composio Python SDK 文档生成器:基于 griffe 的 MDX 参考文档自动化流水线
【免费下载链接】composioComposio powers 1000+ toolkits, tool search, context management, authentication, and a sandboxed workbench to help you build AI agents that turn intent into action.项目地址: https://gitcode.com/GitHub_Trending/co/composio
本文聚焦 Composio 开源仓库中的 SDK 文档生成模块:python/scripts/README.md 与其核心实现 generate-docs.py。该模块使用 griffe 解析 Python 源码与 docstring,自动生成docs/content/reference/sdk-reference/python/下的 MDX 参考文档,并配套回归测试与 CI 自动提 PR 流程。读完本文,你将掌握该文档生成器的运行方式、三类核心配置(EXPECTED_CLASSES、CLASS_MODULES、DECORATORS_TO_DOCUMENT)的作用、MDX 产物结构,以及如何在自己的 Python 项目中复用这套「源码即文档」的生成模式。
一、背景:为什么 SDK 参考文档需要自动生成
Composio 的 Python SDK(python/composio/sdk.py)是一个公开 API 面较大的包:以Composio类为入口,向下暴露tools、toolkits、triggers、connected_accounts、auth_configs、mcp等多个子模块对象,每个对象又包含大量方法与参数。如果全部手写文档,极易出现「源码改了、文档忘了同步」的问题,且方法签名、参数默认值、返回类型等信息手抄成本高、错误率也高。
该模块的解决方案是「源码即事实」:由 griffe 直接读取源码中的类型注解与 docstring,把结构化数据转换为 MDX 文件,再通过 CI 在源码变更后自动生成并提交 PR。整个链条保证了参考文档与实现保持同源,这也是开发者引用参考文档时能放心依赖其准确性的根本原因。
二、快速开始:一条命令生成全部文档
按 python/scripts/README.md 中的说明,在仓库根目录下执行:
cd python uv run --with griffe python scripts/generate-docs.py其中:
cd python:生成脚本 generate-docs.py 位于python/scripts/下,其脚本内PACKAGE_DIR = SCRIPT_DIR.parent会把python/作为待分析包根目录与 griffe 的搜索路径;uv run --with griffe:使用 uv 临时注入 griffe 依赖后运行脚本,无需预先修改项目的依赖清单。若环境中没有 griffe,脚本会打印Error: griffe not installed. Run: pip install griffe并以非零状态退出(见 generate-docs.py 中load_griffe()的懒加载逻辑);- 输出目录为仓库根下的
docs/content/reference/sdk-reference/python/(由脚本内OUTPUT_DIR常量计算得到)。
运行结束后,控制台会依次打印加载包、发现各个类、处理装饰器以及最终生成统计等信息,例如Done! Generated N class docs + index。
三、工作原理:三步流水线
README 用三个步骤概括了整体流程,结合源码可以展开为更完整的执行序列:
- 提取:griffe 解析
composio/**/*.py,从 docstring、类型注解与类/方法结构中得到结构化数据。对应源码中griffe.load("composio", search_paths=[str(PACKAGE_DIR)])的调用; - 转换:
generate-docs.py将结构化数据转换为 MDX 文件——为每个公开类生成独立页面,并生成索引页与导航配置; - 输出:全部文件写入
docs/content/reference/sdk-reference/python/,包括每个类的.mdx页面、index.mdx汇总页与meta.json导航清单。
实际执行时main()函数的完整顺序如下(可对照 generate-docs.py 验证):
- 懒加载 griffe,校验环境;
- 清理并重建输出目录(
shutil.rmtree+mkdir); - 加载
composio包,定位sdk模块中的Composio类; - 遍历
CLASS_MODULES中的模块,在成员里查找EXPECTED_CLASSES声明的类,同时建立「属性名 → 类名」映射(prop_to_class),供Composio页面的属性交叉链接使用; - 补充处理
ADDITIONAL_CLASSES中那些不以composio.<属性>方式直接暴露、但仍属公开 API 的类(如ToolRouterSession); - 对每个类执行
extract_class_info,提取属性、方法、参数、返回值与示例; - 处理
DECORATORS_TO_DOCUMENT声明的修饰器并生成文档片段; - 生成
index.mdx与meta.json。
四、配置详解:三类核心配置项
README 列出三个核心配置,源码中还有若干辅助配置共同决定「文档化哪些内容」。
4.1EXPECTED_CLASSES:类名到Composio属性的映射
EXPECTED_CLASSES = { "Tools": "tools", "Toolkits": "toolkits", "Triggers": "triggers", "ConnectedAccounts": "connected_accounts", "AuthConfigs": "auth_configs", "MCP": "mcp", }- 键:类名(如
Tools); - 值:该类在
Composio实例上对应的属性名(如composio.tools)。
该映射的意义在于:生成Composio类页面时,属性表格中的tools、toolkits等条目会被渲染为指向对应类页面的链接(类型列显示为`Tools`等类名),形成「入口类 → 子模块类」的交叉引用结构。实际产物可见 composio.mdx 的 Properties 表格。
同时该映射也用于在 sdk.py 的__init__中确认这些属性确实由构造器初始化(self.tools = Tools(...)、self.toolkits = Toolkits(...)等),保证「文档声明的 API」与「运行时存在的 API」一一对应。
4.2CLASS_MODULES:类搜索范围
CLASS_MODULES = [ "core.models.tools", "core.models.toolkits", "core.models.triggers", "core.models.connected_accounts", "core.models.auth_configs", "core.models.mcp", ]脚本按点号逐级下钻 griffe 的package.members树,只有出现在这些模块中的类才会被纳入文档范围。与EXPECTED_CLASSES一一对应的 6 个模块,恰好覆盖了 SDK 的主要子领域:工具、工具包、触发器、连接账户、认证配置与 MCP。每个类找到后,其访问路径会被标记为composio.<property>(如composio.tools),并打印Found Tools (via composio.tools)之类的日志。
4.3DECORATORS_TO_DOCUMENT:需要文档化的修饰器
DECORATORS_TO_DOCUMENT = [ ("before_execute", "composio.core.models._modifiers"), ("after_execute", "composio.core.models._modifiers"), ("before_file_upload", "composio.core.models._modifiers"), ("schema_modifier", "composio.core.models._modifiers"), ]每个元组的第一个元素是装饰器函数名,第二个元素是其在包内的模块路径。这 4 个装饰器全部位于 python/composio/core/models/_modifiers.py,是 SDK 的自定义工具修饰能力:before_execute/after_execute分别在工具执行前后改写请求参数或响应,before_file_upload拦截文件上传(返回新路径/URL 或False中止上传),schema_modifier在运行期修改工具 schema。生成器会为每个装饰器渲染一段签名示例,例如@before_execute(modifier=..., tools=..., toolkits=...)配合def my_modifier(...)占位,帮助用户理解修饰器的调用形态;完整说明可见 index.mdx 的 Decorators 小节。
4.4 辅助配置:过滤、重命名与补充
源码中还定义了以下几组影响文档产物的辅助配置:
SKIP_CLASSES:{"WithLogger", "SDKConfig", "TProvider"},过滤日志基类、SDK 配置 TypedDict 与泛型占位等内部/辅助类;ADDITIONAL_CLASSES:{"ToolRouterSession": "core.models.tool_router_session"},补充那些不通过composio.<属性>暴露、但属于公开 API 的类(源码注释特别说明SessionContextImpl因属内部实现细节而刻意不收录);DISPLAY_NAME_OVERRIDES:{"ToolRouterSession": "Session"},实现「源码类名不变、文档展示名规范化为 Session」的纯展示层重命名;SLUG_OVERRIDES:{"ToolRouterSession": "session"},控制输出文件名与 URL slug。
正是后两组配置,使 session.mdx 以Session名称对外呈现,同时meta.json中登记为session页,而无需对源码做破坏性改名。
五、输出产物:MDX 文件的结构
5.1 目录清单
运行生成器后,docs/content/reference/sdk-reference/python/下会包含(与当前仓库现状一致):
index.mdx:汇总页,含安装提示、类清单表格、Quick Start 代码示例与 Decorators 小节;composio.mdx、tools.mdx、toolkits.mdx、triggers.mdx、connected-accounts.mdx、auth-configs.mdx、mcp.mdx、session.mdx:每个类的独立页面;meta.json:Fumadocs 导航元数据,pages数组按composio → tools → ... → session的顺序声明页面(与SLUG_OVERRIDES保持一致)。
5.2 单页结构(以tools.mdx为例)
每个类页面由generate_class_mdx()生成,典型结构为:
- YAML frontmatter:
title与description,description 取类 docstring 首段并做长度截断(超过 150 字符截为 147 字符加省略号),同时会把 reStructuredText 风格的双反引号 code 规范化为单反引号; - 弃用提示:若类 docstring 含
.. deprecated::指令,则渲染为<Callout type="warn" title="Deprecated">警告块; - Properties 表格:列出公开属性(跳过下划线开头成员);当属性名命中
prop_to_class时渲染为指向类页面的 Markdown 链接,类型列显示类名;当属性无描述时自动降级为两列表格; - Methods 小节:每个方法包含描述、Python 签名代码块(参数按
name: type输出,有默认值的标记= ...)、参数表格(?后缀标注可选参数,|转义为\|以兼容表格)、返回值说明(None/Any省略)、示例代码块,方法之间以---分隔; - View source 链接:页面底部为每个对象输出指向源码文件行号位置的链接(由 griffe 提供的
filepath与lineno计算得出)。
以 tools.mdx 为例,读者可以看到get()、execute()、proxy()、get_raw_tool_router_meta_tools()等方法的完整签名与参数表,其中get()的返回类型按 provider 泛型动态推断(如 OpenAIProvider 返回list[ChatCompletionToolParam]),这正体现了生成器对泛型标注的忠实呈现。
六、docstring 与类型的规范化处理
为了让生成文档「可读、可复制」,脚本对原始源码信息做了多层规范化:
- 类型清理(
format_type):去掉typing.、typing_extensions.、composio.client.types.等前缀;将Optional[X]改写为X | None;把Unpack[...]简化为内部类型;超过 60 字符的超长类型截断为 57 字符加...; - docstring 分区解析(
parse_docstring):逐行识别:param name:、:returns:/:return:、Example区段与.. deprecated::指令,分别归入 description、params、returns、examples、deprecated 字段;多行描述会正确拼接; - 示例规范化(
normalize_example):用textwrap.dedent去除缩进,若示例自身带有 python ... 围栏则剥离围栏内容,避免生成「嵌套代码块」的非法 MDX。
这些细节并非无关紧要——回归测试 python/tests/test_generate_docs.py 专门验证了两点:Triggers.parse()生成的示例必须是可直接ast.parse的合法 Python(保证「复制即用」);docstring 示例中的嵌套 Markdown 围栏会被剥离,不会污染最终 MDX。
七、测试保障:回归测试如何守护产物质量
测试文件通过importlib.util.spec_from_file_location动态加载scripts/generate-docs.py(不执行main(),仅导入模块),从而在无 griffe 的测试环境下单测解析逻辑,这正是脚本把 griffe 做成懒加载的原因。测试内容:
test_triggers_parse_generated_example_is_valid_python:用真实类的Triggers.parse.__doc__跑parse_docstring,断言示例存在且可通过ast.parse语法校验,防止 docstring 改动后生成不可复制的示例代码;test_generated_examples_do_not_keep_nested_markdown_fences:验证normalize_example会剥离示例内嵌的 python 围栏。
也就是说,文档生成器自身也受 CI 测试保护,任何会让「生成的示例代码失配」的 docstring 变更都会在测试阶段被拦截。
八、CI 自动化:源码变更自动生成并提交 PR
README 提到的.github/workflows/generate-sdk-docs.yml在仓库中真实存在,其generate-python-docsjob 完整实现了「触发 → 生成 → 提 PR → 请求评审」的闭环:
- 触发条件:
push到next分支,且路径匹配python/composio/**、python/scripts/generate-docs.py、.github/workflows/generate-sdk-docs.yml、mise.toml/mise.lock等;同时支持workflow_dispatch手动触发; - 运行步骤:生成 GitHub App token → checkout → 用
setup-python-uvaction 准备 uv 环境 → 执行cd python && uv run --with griffe python scripts/generate-docs.py; - 提 PR:使用
peter-evans/create-pull-request将docs/content/reference/sdk-reference/python/目录的变更提交为标题为docs: update Python SDK reference from source的 PR,base 分支为next,并自动把提交者添加为 reviewer。
值得留意的是,同一个工作流还包含generate-ts-docsjob,对应 TypeScript 侧的文档生成(pnpm --filter @composio/core generate:docs),说明「源码变更自动同步 SDK 参考文档」是整个仓库的通用工程实践,Python 侧只是其中一半。该工作流还约束了permissions: contents: read的最小权限原则,仅在需要写回内容的 job 内放开contents: write与pull-requests: write。
九、落地实践:如何把该模式复用到自己的项目
这套生成器的设计对任何维护 Python SDK 文档的团队都有直接借鉴价值:
- 让文档生成成为构建步骤的一部分:与手写文档相比,griffe 直接从类型注解与 docstring 提取信息,签名与参数永远与源码同步;
- 用配置声明「文档化范围」:用「类名 → 入口属性」映射和「模块列表」精确圈定公开 API,配合
SKIP_CLASSES屏蔽内部类,避免把实现细节泄露进面向用户的参考文档; - 展示层与源码解耦:
DISPLAY_NAME_OVERRIDES/SLUG_OVERRIDES这类纯展示覆盖,让团队可以在不破坏源码兼容性的前提下规范化文档中的类名与 URL; - 用测试守护生成器自身:像 test_generate_docs.py 那样,把「生成的示例必须可运行、生成的 MDX 必须合法」固化为自动化断言;
- 用 CI 完成闭环:在源码路径变更时自动重新生成并提 PR,配合人工评审,让文档更新成为可追踪、可审查的常规流程。
如果你需要在本仓库中查看最终产物,可直接阅读 index.mdx(总览与 Quick Start)、composio.mdx(入口类属性交叉链接)以及 tools.mdx(方法级参考页范式),并结合 generate-docs.py 源码理解每段产物背后的生成逻辑。
【免费下载链接】composioComposio powers 1000+ toolkits, tool search, context management, authentication, and a sandboxed workbench to help you build AI agents that turn intent into action.项目地址: https://gitcode.com/GitHub_Trending/co/composio
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考