
Ethan Collins
Pattern Recognition Specialist

sessions: write权限(返回403)和工具的第一个参数缺少Pydantic BaseModel注解(触发ValidationError)。本指南将CapSolver与Composio集成,作为完成reCAPTCHA v2工作流的代理工具。该工具不仅返回令牌,还会运行完整的页面序列,并将页面的实际响应视为成功条件。OpenAI代理SDK决定何时调用该工具,而Playwright浏览器自动化保留用于提交和验证的页面上下文。
仅在合法、合理、负责任且获得用户授权的工作流中使用此模式。技术能力不意味着有权访问私有、受限、敏感或未经授权的数据;部署前请查阅相关AI自动化指南。
工作流:
运行脚本
-> OpenAI代理SDK决定调用哪个工具
-> Composio自定义工具: complete_recaptcha_v2
-> Playwright打开页面
-> capsolver.solve(...)返回gRecaptchaResponse
-> 将令牌应用到g-recaptcha-response
-> Playwright提交并等待页面
-> 读取页面并判断是否通过
-> 工具返回 {"accepted": ..., "message": ...}
-> 代理报告accepted的结果
各组件职责如下:
| 组件 | 职责 |
|---|---|
| OpenAI代理SDK | 理解自然语言指令,决定何时调用工具,执行工具并整理响应 |
| Composio | 将标准Python函数注册为代理可调用的工具 |
| Playwright | 打开页面,应用结果,提交表单并读取结果页面状态 |
| CapSolver SDK | 通过单次solve()调用返回CAPTCHA结果 |
pip install composio composio-openai-agents openai-agents capsolver pydantic playwright
playwright install chromium
每个依赖项都有特定作用:
| 包 | 目的 |
|---|---|
| composio | 创建会话并注册或加载自定义工具 |
| composio-openai-agents | 将Composio工具转换为OpenAI代理可调用的对象 |
| openai-agents | 提供Agent、Runner和SQLite多轮记忆 |
| capsolver | 提供官方SDK并通过solve()返回结果 |
| pydantic | 定义工具输入模式 |
| playwright | 打开页面,应用结果,提交表单并读取响应 |
# API密钥。
COMPOSIO_API_KEY = "ak_..."
OPENAI_API_KEY = "sk-..." # 您的官方OpenAI API密钥。
os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY # OpenAI SDK从环境变量中读取密钥。
# 配置CapSolver和Composio。
capsolver.api_key = "CAP-..."
composio = Composio(
api_key=COMPOSIO_API_KEY,
provider=OpenAIAgentsProvider(),
)
配置说明:
OPENAI_API_KEY必须写入环境变量,因为SDK从那里读取;OpenAIAgentsProvider使session.tools()返回的工具与Agent兼容;Composio密钥需要sessions: write权限,否则会话创建返回403。
当前Composio OpenAI提供者和OpenAI代理SDK参考文档解释了此配置使用的提供者和代理边界。
领取您的CapSolver优惠码
立即提升您的自动化预算!
在充值CapSolver账户时使用优惠码CAP26,每次充值可获得5%的额外奖励——无限制。
现在在您的CapSolver仪表板中领取
停止条件: 仅当页面包含预期的成功文本时,工具才报告成功。
finally块在成功和失败路径中都关闭浏览器。
import os
from typing import List, cast
import capsolver
from agents import Agent, Runner, SQLiteSession
from composio import Composio
from composio.core.models.custom_tool import CustomTool
from composio.core.models.tool_router import ToolRouterExperimentalConfig
from composio_openai_agents import OpenAIAgentsProvider
from playwright.sync_api import sync_playwright
from pydantic import BaseModel, Field
# API密钥。
COMPOSIO_API_KEY = "ak_..."
OPENAI_API_KEY = "sk-..." # 您的官方OpenAI API密钥。
os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY
# 配置CapSolver和Composio。
capsolver.api_key = "CAP-..."
composio = Composio(
api_key=COMPOSIO_API_KEY,
provider=OpenAIAgentsProvider(),
)
# 自定义工具的输入模式;Composio要求此处为Pydantic BaseModel。
class CompleteRecaptchaInput(BaseModel):
target_url: str = Field(
default="https://www.google.com/recaptcha/api2/demo",
description="包含reCAPTCHA v2演示的页面URL",
)
website_key: str = Field(
default="6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
description="当前页面的reCAPTCHA v2网站密钥",
)
# 将整个流程注册为一个Composio工具,代理可调用。
# 第一个参数的类型注解是Composio推断模式所必需的。
@composio.experimental.tool(preload=True)
def complete_recaptcha_v2(input: CompleteRecaptchaInput, _ctx):
"""使用Playwright打开页面,解决reCAPTCHA v2,提交并验证。"""
with sync_playwright() as p:
browser = p.chromium.launch(headless=False) # 设置headless=True以隐藏窗口。
page = browser.new_page()
try:
page.goto(input.target_url)
# 请求CapSolver解决reCAPTCHA v2挑战。
solution = capsolver.solve(
{
"type": "ReCaptchaV2TaskProxyLess",
"websiteURL": input.target_url,
"websiteKey": input.website_key,
}
)
token = solution.get("gRecaptchaResponse")
page.evaluate(
"""
(token) => {
const textarea = document.getElementById('g-recaptcha-response');
if (textarea) {
textarea.value = token;
}
}
""",
token,
)
page.click("#recaptcha-demo-submit")
page.wait_for_load_state("networkidle")
result_page = page.content()
# 仅当页面实际显示成功文本时才视为成功
accepted = "Verification Success" in result_page
return {
"accepted": accepted,
"message": (
"Verification Success"
if accepted
else "页面未报告Verification Success"
),
}
finally:
browser.close()
def main():
experimental: ToolRouterExperimentalConfig = {
"custom_tools": cast(List[CustomTool], [complete_recaptcha_v2]),
}
session = composio.sessions.create(
user_id="playwright-recaptcha-demo-user",
experimental=experimental,
sandbox={"enable": False}, # 在此进程中运行工具,而非沙箱。
)
agent = Agent(
name="Playwright reCAPTCHA助手",
instructions=(
"当用户要求运行演示时,使用默认值调用complete_recaptcha_v2 "
"。仅当accepted为true时报告成功。"
),
model="gpt-5.2",
tools=session.tools(),
)
# 多轮对话的内存
memory = SQLiteSession("conversation")
print("Composio + Playwright reCAPTCHA v2演示正在运行...")
user_input = (
"现在使用默认的target_url和website_key调用complete_recaptcha_v2 "
"。不要询问确认。"
)
result = Runner.run_sync(
starting_agent=agent,
input=user_input,
session=memory,
)
print(f"助手: {result.final_output}\n")
if __name__ == "__main__":
main()
相同模式可以处理标准图片文本CAPTCHA,通过注册第二个Composio工具。此示例使用BotDetect CAPTCHA演示:图片元素为#demoCaptcha_CaptchaImage,输入为#captchaCode,验证按钮为#validateCaptchaButton。

ImageToTextTask请求通过body提交Base64图像。与基于令牌的任务不同,此任务直接返回识别文本,无需单独轮询循环。
image_src = page.locator("#demoCaptcha_CaptchaImage").get_attribute("src")
if not image_src or "," not in image_src:
raise RuntimeError("未找到有效的CAPTCHA图片Data URL")
base64_image = image_src.split(",", 1)[1] # 去除"data:image/...;base64,"前缀。
class CompleteImageCaptchaInput(BaseModel):
target_url: str = Field(
default="https://captcha.com/demos/features/captcha-demo.aspx",
description="图片CAPTCHA演示页面URL",
)
module: str = Field(
default="common",
description="CapSolver ImageToTextTask识别模块",
)
@composio.experimental.tool(preload=True)
def complete_image_captcha(input: CompleteImageCaptchaInput, _ctx):
"""使用Playwright打开页面,识别图片CAPTCHA,提交并验证。"""
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
try:
page.goto(input.target_url)
page.wait_for_selector("#demoCaptcha_CaptchaImage", state="visible")
# 图片src已经是数据URL;去除前缀以获取Base64。
image_src = page.locator("#demoCaptcha_CaptchaImage").get_attribute("src")
if not image_src or "," not in image_src:
raise RuntimeError("未找到有效的CAPTCHA图片Data URL")
base64_image = image_src.split(",", 1)[1]
solution = capsolver.solve(
{
"type": "ImageToTextTask",
"websiteURL": input.target_url,
"module": input.module,
"body": base64_image,
}
)
captcha_text = solution.get("text")
if not isinstance(captcha_text, str) or not captcha_text:
raise RuntimeError("CapSolver未返回识别文本")
page.fill("#captchaCode", captcha_text) # 填写识别文本。
page.click("#validateCaptchaButton")
page.wait_for_load_state("networkidle")
result_page = page.content()
# 演示页面在成功时显示"Correct!",失败时显示"Incorrect!"。
accepted = "Correct!" in result_page
return {
"accepted": accepted,
"recognized_text": captcha_text,
"message": "Correct!" if accepted else "页面未报告Correct!",
}
finally:
browser.close()
流程概述:
Playwright打开CAPTCHA页面
-> 等待#demoCaptcha_CaptchaImage可见
-> 读取src(数据URL)并去除前缀以获取Base64
-> capsolver.solve(ImageToTextTask)返回文本
-> page.fill将结果写入#captchaCode
-> page.click激活#validateCaptchaButton
-> page.content检查Correct!或Incorrect!
-> finally关闭浏览器
module参数是可选的,默认为common。如果CAPTCHA仅包含数字,请使用number。特殊样式可在适当情况下使用文档记录的独立模型。

例如,以下源代码可直接用于纯数字识别:
solution = capsolver.solve({
"type": "ImageToTextTask",
"module": "number",
"images": [base64_image],
})
answers = solution["answers"]
number模型支持一次提交多个图像,images最多可包含九个Base64字符串。支持的模型名称和用例列在上述CapSolver ImageToTextTask页面中。
experimental.tool: "complete_recaptcha_v2"的第一个参数必须
标注为Pydantic BaseModel子类。得到: <class 'inspect._empty'>
Composio从第一个参数的类型注解推断输入模式,因此input: CompleteRecaptchaInput不能省略。这是一个功能注解,而不是可选类型提示。Pydantic BaseModel参考文档描述了用于模式的模型类型。
会话创建可能会返回以下错误:
403 APIKey_InsufficientPermissions
此路由需要 "sessions" 写入权限
原因是 composio.sessions.create() 需要项目密钥的写入权限来处理会话,而当前密钥只有只读权限。密钥有效,但其作用域不足,因此返回 403 而不是 401。
解决步骤:
sessions: write 的新密钥,并替换脚本顶部的 COMPOSIO_API_KEY。此集成的核心是一个打包为 Composio 工具的完整业务流程:
Composio 工具 = Playwright 页面操作 + CapSolver 结果 + 页面状态验证
仅在您拥有或授权自动化的页面和进程中运行示例。使用环境变量或密钥管理器处理凭证,在页面未达到预期业务状态时停止操作,并审查重复失败情况而非无限重试。
对于需要专注 CAPTCHA 基础设施层的授权 Composio 代理工作流,使用您控制的页面测试 CapSolver,并在每次求解后验证应用结果。
Composio 在此集成中处理什么?
Composio 将 Python 函数注册为代理可调用的自定义工具,创建会话,暴露工具模式,并从 OpenAI 代理路由执行。
为什么第一个工具参数必须是 Pydantic BaseModel?
Composio 使用该注解来推断工具的输入模式。省略它会阻止模式构建,并在浏览器工作流开始前引发验证错误。
reCAPTCHA v2 工具在 CapSolver 返回令牌后会停止吗?
不会。代码保持不变,应用令牌,提交演示表单,读取结果 HTML,并仅在页面包含预期的“Verification Success”文本时报告成功。
ImageToTextTask 是否需要单独的轮询循环?
不需要。在此工作流中,官方 SDK 会直接返回识别文本。工具随后填写输入,提交页面,并以“Correct!”作为停止条件进行检查。
此工作流能否用于任何网站?
不能。仅用于合法、合理、负责任且用户授权的自动化。尊重网站条款、适用法律、速率限制和数据最小化要求。
一个AI代理reCAPTCHA v3求解器只有在代理保留产生挑战的操作、页面、浏览器会话和授权上下文时才是可靠的。CapSolver通过Core SDK、Agent Tools和MCP提供经过记录的CAPTCHA基础设施层。代理仍然负责策略、重试和原始任务的确认。本指南解释了reCAPTCHA v3(包括企业版)的生产环境集成,而不将返回的令牌视为最终的成功结果。

当一个AI代理的验证码无法工作报告到达时,这个短语隐藏了多种不同的故障。检测可能有误,代理可能被路由到不可用的工具,浏览器可能在结果返回前导航,或者应用程序可能拒绝一个技术上已生成的结果。CapSolver提供已记录的CAPTCHA基础设施,而您的协调器必须保留证据并选择正确的恢复分支。本指南将模糊的事件转化为分层的
