每天早上9点,某公司行政部的小张都要处理近20条请假申请核对------员工们在OA网页上填错日期、漏选假种、忘记附理由是常事;而研发部的小李,为了把"每月考勤对账"接入自动化流程,写了一堆浏览器脚本,结果OA前端一改版,脚本全部失效,还要重新调试DOM元素;更糟的是,尝试让AI协助处理审批的团队,曾因AI误点"驳回并归档"按钮,导致3条重要的加班调休申请被错误处理,复盘了整整两天。
这就是多数企业OA系统的现状:对人可用,对自动化/AI极不友好。员工手工操作能完成的登录、查余额、提请假、看审批,一旦想接入自动化或AI,就会暴露底层能力未抽象、操作不可控、风险无边界的核心问题。
OA的核心能力(如请假提交、审批流转)藏在网页交互背后,外部无法获取稳定、可复用、可组合的接口语义:
很多团队用Selenium/Puppeteer做网页自动化,或让AI直接控制浏览器,看似解决了"自动操作",但存在致命问题:
查询类操作(查假种、余额)风险低,但审批、提单、驳回等动作一旦误触发,影响的是真实业务单据:
反模式(脆弱且高风险):

最优解(稳定且可控):

为什么要先做oa-cli?
oa-cli 不是"换个方式点网页",而是把OA高频动作抽象成稳定、可治理、带管控的命令,收拢页面分散的流程、字段、校验和异常处理能力。
# 认证相关oa-cli auth login --username zhangsan --password-env OA_PWD # 密码从环境变量读取,避免明文oa-cli auth status # 输出JSON格式的登录状态oa-cli auth logout --clean-cache # 登出并清理本地会话缓存# 请假相关oa-cli leave types # 查询所有可用假种(年假/事假/病假等)oa-cli leave balance --type annual # 查询年假余额oa-cli leave list --start 2026-01-01 --end 2026-04-01 # 查询指定时间段请假记录oa-cli leave preview --type annual --start "2026-04-10 09:00" --end "2026-04-10 18:00" --reason "事假" # 预览提交结果(无实际提交)oa-cli leave submit --type annual --start "2026-04-10 09:00" --end "2026-04-10 18:00" --reason "事假" --confirm --dry-run=false # 确认提交(--dry-run=true时仅预览)oa-cli leave cancel --apply-id 12345 --confirm # 撤销请假申请(高风险操作需确认)人、脚本、AI面对的是统一参数(如日期格式、假种枚举)和结构化输出(JSON),而非不确定的网页交互;
示例输出:oa-cli leave balance --type annual*
{ "code": 0, "msg": "success", "data": { "employee_id": "10086", "annual_leave_total": 10, "annual_leave_used": 3, "annual_leave_remaining": 7, "update_time": "2026-04-01 15:30:00" }}工具层统一实现关键管控,无需使用者自行处理:
--dry-run:预览操作结果,无实际提交;--confirm:高风险操作强制人工确认;AI仅能调用白名单命令,高风险动作(如提交、撤销、审批)保留人工确认门槛,杜绝无约束操作。
如果跳过CLI层,直接让AI对接OA网页/底层接口,只会放大现有问题:
| 对接方式 | 稳定性 | 可管控性 | 误操作风险 | 可维护性 |
|---|---|---|---|---|
| AI 直接控制浏览器 | 极低(前端改版即失效) | 无(无法管控AI点击行为) | 极高(不可逆操作易误触发) | 极低(需适配DOM/页面逻辑) |
| AI 调用底层接口 | 中(接口变更需适配) | 低(需手动管控参数/权限) | 中(参数错误易导致业务异常) | 中(需维护接口签名/参数) |
| AI 调用封装后的CLI | 高(CLI屏蔽底层变化) | 高(内置确认/审计/幂等) | 低(仅开放白名单+人工确认) | 高(聚焦业务动作,而非底层交互) |
这类系统最怕"一步到位做平台",更高效的方式是按阶段落地,每个阶段聚焦"最小闭环":
核心目标:明确OA的技术细节,决定Stage 1的接入方式(API/浏览器自动化)。
需确认的关键信息:
| 维度 | 需确认的内容 | 应对方案示例 |
|---|---|---|
| 登录方式 | 账号密码/短信验证码/单点登录(SSO)? | 验证码:对接平台/人工扫码;SSO:解析token生成逻辑 |
| 会话机制 | 会话凭证(Cookie/Token)、过期时间、刷新逻辑 | 本地加密存储Cookie,定时调用auth status检测过期 |
| 表单校验 | 请假表单的隐藏字段(如部门ID)、前置校验(如年假余额是否足够) | 提前抓取表单元数据,CLI层内置校验逻辑 |
| 接口安全 | 是否有CSRF Token/请求签名/跨域限制? | CSRF:抓取页面的CSRF Token并带入请求;跨域:通过代理转发 |
核心目标 :跑通"登录→查假→提请假"的最小闭环,产出可用的oa-cli基础版本。
核心功能&实操代码示例:
# oa_cli/auth.pyimport jsonimport osimport cryptography.fernet # 加密存储会话信息from requests import Sessiondef login(username: str, password: str) -> dict: """登录OA,返回会话信息并加密存储到本地""" sess = Session() # 1. 对接OA登录接口(优先)或用Playwright模拟登录(兜底) login_res = sess.post("https://oa.example.com/api/login", data={ "username": username, "password": password, "csrf_token": get_csrf_token(sess) # 抓取页面CSRF Token }) # 2. 验证登录结果 if login_res.json()["code"] != 0: raise Exception(f"登录失败:{login_res.json()['msg']}") # 3. 加密存储会话信息(Cookie/Token) cipher = cryptography.fernet.Fernet(os.getenv("OA_CLI_SECRET_KEY")) session_data = json.dumps(dict(sess.cookies)) with open("~/.oa-cli/session", "wb") as f: f.write(cipher.encrypt(session_data.encode())) return {"code": 0, "msg": "登录成功"}def status() -> dict: """检查登录状态""" # 解密读取本地会话,调用OA状态接口 # ... 省略实现 ... return {"code": 0, "data": {"is_login": True, "expire_time": "2026-04-10 23:59:00"}}实现leave types/balance/preview/submit命令,内置--dry-run预览、--confirm确认逻辑;
用加密方式存储会话信息(避免明文密码/Token泄露);
标准化错误码(如1001=登录失效、2001=年假余额不足),便于排查问题。
核心目标:补充审批相关能力,完善审计日志,支持团队级使用。
新增功能:
oa-cli approval list --pending;oa-cli approval approve --id 12345 --comment "同意" --confirm;核心目标:将CLI封装为AI可调用的接口,限定AI的操作边界。
落地方式:
核心目标:补齐企业级治理能力,从PoC升级为生产级工具。
核心治理能力:
leave balance)做限流,对临时接口失败自动重试;| 问题场景 | 解决方案 |
|---|---|
| OA 登录需要验证码 | 1. 优先申请企业免验证权限; 2. 对接平台自动识别; 3. 支持人工扫码登录,缓存会话 |
| 会话频繁过期 | 1. 定时调用auth status检测会话状态; 2. 会话过期时自动触发重新登录; 3. 延长OA会话超时时间(需运维配合) |
| 前端无公开接口,只能用浏览器自动化 | 1. 用Playwright/Puppeteer封装底层操作,对外暴露稳定CLI; 2. 前端DOM变化,通过特征(而非固定ID)定位元素; 3. 前端改版时仅需修改自动化层,CLI命令保持不变 |
| AI 误触发高风险命令 | 1. 高风险命令需人工回复“确认”才能执行; 2. 给AI返回“操作需确认”的提示,而非直接执行; 3. 限制AI每日调用高风险命令的次数 |
--human参数输出人类友好的文本;--confirm强制确认、操作日志审计、基于请求ID的幂等保护;一个只能被"人工点击"的OA系统,永远无法真正融入企业自动化/AI协作体系。
我们不是要"让AI代替人操作OA",而是要先把OA的核心能力从"网页交互"收敛成"可复用、可管控、可审计的CLI工具",再让AI在这个安全边界内发挥价值。
这套思路的核心不是技术多先进,而是先解决"可控性",再解决"智能化" ------承认传统OA的复杂性,不把AI当"万能胶",而是通过工程化的方式,让OA能力真正成为企业可复用的数字化资产。
",