用 Omnigent 构建安全的多智能体财务工作流
教程展示如何集成实时数据、实现多层级智能体协作和成本治理策略,实现端到端财务分析工作流。
教程展示如何集成实时数据、实现多层级智能体协作和成本治理策略,实现端到端财务分析工作流。
人工智能
在本教程中,我们使用 uv 创建可靠且隔离的 Python 环境,并通过 Omnigent 构建和执行一个多 Agent 工作流。我们配置了一个金融研究主管 Agent:它会从外部 API 获取实时的 USD 兑 EUR 汇率,准备一份简洁、可直接交付给客户的摘要,并将草稿委派给专门的文本审核子 Agent,由其检查文本的清晰度和长度。我们将可复用的 Python 函数定义为 Agent 可调用的工具,使用 YAML 描述完整的 Agent 结构,并以 Claude Agent SDK 作为执行框架。我们还通过环境变量安全地管理 Anthropic API key,应用非交互式策略来限制工具调用次数和控制会话成本,并直接在 Colab 中运行工作流,无需 Node.js、tmux 或交互式终端。通过这一实现,我们将探索 Omnigent 如何在一个可配置系统中整合 Agent、工具、任务委派、实时数据访问和治理能力。
import os, sys, subprocess, textwrap, pathlib, getpass
def sh(cmd, **kw):
"""Run a command, and on failure show the ACTUAL error, not just a code."""
print("$", " ".join(map(str, cmd)))
p = subprocess.run(cmd, text=True, capture_output=True, **kw)
if p.returncode != 0:
print(p.stdout or "", p.stderr or "", sep="\n")
raise RuntimeError(f"Command failed ({p.returncode}): {' '.join(map(str, cmd))}")
return p
WORKDIR = pathlib.Path("/content/omnigent_tutorial")
WORKDIR.mkdir(parents=True, exist_ok=True)
VENV = WORKDIR / ".venv"
subprocess.run([sys.executable, "-m", "pip", "install", "-q", "uv"], check=True)
if not (VENV / "bin" / "python").exists():
sh(["uv", "venv", "--python", "3.12", str(VENV)])
PY = str(VENV / "bin" / "python")
sh(["uv", "pip", "install", "--python", PY, "-q", "omnigent", "requests"])
OMNI = str(VENV / "bin" / "omnigent")
print("\n✅", subprocess.run([OMNI, "--version"], capture_output=True, text=True).stdout.strip())
我们导入所需的 Python 模块,并定义一个辅助函数来执行 shell 命令。当命令执行失败时,该函数会显示详细的错误信息。我们创建一个专用工作目录,并使用 uv 构建隔离的 Python 3.12 虚拟环境,从而绕过 Colab 对 ensurepip 的限制。随后,我们在该环境中安装 Omnigent 和 Requests,定位 Omnigent CLI 可执行文件,并通过输出版本号来验证安装是否成功。
if not os.environ.get("ANTHROPIC_API_KEY"):
os.environ["ANTHROPIC_API_KEY"] = getpass.getpass("Anthropic API key: ")
env = os.environ.copy()
env["OMNIGENT_NO_UPDATE_CHECK"] = "1"
只有当 notebook 环境中尚未提供 Anthropic API key 时,我们才会安全地要求用户输入。我们将凭据存储在当前进程的环境变量中,使 Omnigent 无需把敏感信息写入文件即可读取它。我们还为子进程创建一份独立的环境配置,并在执行期间关闭 Omnigent 的自动更新检查。
(WORKDIR / "agent_tools.py").write_text(textwrap.dedent('''
"""Local tools exposed to the Omnigent agents in this tutorial."""
import requests
def get_exchange_rate(base_currency: str, target_currency: str) -> dict:
"""Look up the latest FX rate between two ISO-4217 currency codes."""
r = requests.get(
"https://api.frankfurter.app/latest",
params={"from": base_currency.upper(), "to": target_currency.upper()},
timeout=10,
)
r.raise_for_status()
data = r.json()
return {
"base": base_currency.upper(),
"target": target_currency.upper(),
"rate": data["rates"][target_currency.upper()],
"date": data["date"],
}
def word_count(text: str) -> int:
"""Count the words in a piece of text."""
return len(text.split())
'''))
我们生成一个 Python 模块,其中包含 Omnigent 以可调用工具形式提供给 Agent 的本地函数。我们定义了一个实时汇率工具:它向 Frankfurter API 发送请求,并返回最新汇率、货币代码和适用日期。我们还实现了一个简单的字数统计工具,供审核子 Agent 衡量金融摘要的长度。
(WORKDIR / "fx_research_lead.yaml").write_text(textwrap.dedent('''
name: fx_research_lead
prompt: |
You are a financial research lead. For any question about currency
movements: call get_exchange_rate to fetch the live rate, then hand
your draft summary to the text_auditor sub-agent for a clarity and
length check before giving your final answer to the user.
executor:
harness: claude-sdk
tools:
get_exchange_rate:
type: function
callable: agent_tools.get_exchange_rate
text_auditor:
type: agent
prompt: |
You audit short pieces of financial writing. Call word_count to
report its length, flag any unexplained jargon, and suggest one
concrete clarity improvement.
tools:
word_count:
type: function
callable: agent_tools.word_count
policies:
cap_calls:
type: function
handler: omnigent.policies.builtins.safety.max_tool_calls_per_session
factory_params:
limit: 20
budget:
type: function
handler: omnigent.policies.builtins.cost.cost_budget
factory_params:
max_cost_usd: 1.00
'''))
我们通过 YAML 配置文件定义完整的多 Agent 架构。我们配置金融研究主管 Agent,将其连接到汇率工具,并添加一个文本审核子 Agent,使用字数统计函数评估草稿。我们还应用了严格的治理策略,限制工具调用次数,并限定本次会话允许产生的最高 API 成本。
env["PYTHONPATH"] = str(WORKDIR)
question = (
"What is the current USD to EUR exchange rate? Give me a two-sentence "
"summary I could paste into a client note."
)
result = subprocess.run(
[OMNI, "run", str(WORKDIR / "fx_research_lead.yaml"), "-p", question, "--no-session"],
cwd=WORKDIR, env=env, stdin=subprocess.DEVNULL,
capture_output=True, text=True, timeout=300,
)
print("\n" + "=" * 70)
print(result.stdout.strip() or "(no stdout)")
if result.returncode != 0 or "error" in result.stdout.lower():
print("-" * 70)
print("stderr:", result.stderr[-2000:])
print(f"\nDebug: check ~/.omnigent/logs/runner/ , or rerun with:\n"
f" !{OMNI} --debug --log-to-stderr run {WORKDIR/'fx_research_lead.yaml'} -p \"...\" --no-session")
print("=" * 70)
print(f"""
Next steps:
• Explore the CLI: !{OMNI} run --help
• Bundled demo agents:
!{OMNI} polly -p "review this repo" --no-session
!{OMNI} debby -p "brainstorm 3 names for a coffee shop" --no-session
• YAML schema: https://github.com/omnigent-ai/omnigent/blob/main/docs/AGENT_YAML_SPEC.md
• Policies: https://github.com/omnigent-ai/omnigent/blob/main/docs/POLICIES.md
""")
我们将教程目录添加到 PYTHONPATH,定义与货币相关的问题,并通过非交互式子进程执行 Omnigent Agent。我们捕获生成的响应,在执行失败时显示诊断输出,并提供用于排查 runner 问题的 debug 命令。最后,我们输出一些实用的后续步骤,帮助读者继续探索 Omnigent CLI、内置 Agent、YAML 规范和策略文档。
总而言之,我们创建了一个实用的 Omnigent 多 Agent 应用,集成了实时金融数据获取、分层 Agent 委派、自动化写作评估以及基于策略的执行控制。我们使用 uv 解决了 Colab 的 ensurepip 限制,在不修改 notebook 系统解释器的前提下维护独立的 Python 3.12 环境。我们将本地 Python 函数开放为 Agent 可访问的工具,通过易读的 YAML 配置定义 Agent 和子 Agent 的行为,并对工具使用量与 API 支出实施严格限制。我们还以非交互方式执行了整个工作流,同时捕获标准输出和诊断错误,并建立了一套无需修改底层 Agent 逻辑即可轻松切换模型的结构。现在,我们已经拥有一个可复用的基础,可用于在 Google Colab 中开发更复杂、更安全、成本可控且支持工具调用的多 Agent 系统,服务于金融研究及其他真实业务场景。
点击此处查看完整代码。也欢迎关注我们的 Twitter,别忘了加入拥有超过 15 万名成员的机器学习 SubReddit,并订阅我们的 Newsletter。等等!你也在使用 Telegram 吗?现在也可以加入我们的 Telegram 社群。
需要与我们合作,推广你的 GitHub Repo、Hugging Face Page、Product Release 或 Webinar 等内容吗?欢迎联系我们。
Sana Hassan 是 MarkTechPost 的咨询实习生,同时也是 IIT Madras 的双学位学生。他热衷于运用技术和 AI 解决现实世界中的挑战。凭借对实际问题解决方案的浓厚兴趣,他为 AI 与现实应用的交汇带来了新颖视角。