1. 100 个 agent 复现 Pokhara Lakeside 经济:先统一 TaoToken Key 与 Base URL
复现 100 个带记忆 LLM agent 在 Pokhara Lakeside 地理小镇经济中的 26 周模拟,最先卡住的通常不是经济学规则,而是百万级决策背后的鉴权与并发。建议在批量运行前先到 TaoToken 官网 获取 Key,并把 API Base URL 设为https://taotoken.net/api。TaoToken 只提供 Key 与 Base URL,不替代 agent 框架、记忆存储、地理引擎或实验逻辑;因此本文重点放在环境变量注入、并发控制、Claude Code / Codex / CC Switch 配置,以及每周指标落表。那项研究把 100 个带记忆的 LLM agent 放进 Pokhara Lakeside 的真实地理小镇经济,跑最长 26 个模拟周,形成 91 次有效运行和约 2.44M 次决策;观察到货币流动趋于停滞,游客冲击放大商业收入却没有同步抬高工资,菜单重定价极少,随机现金转移后大部分资金仍未花出。要复现这种“宏观异常”,你需要的不是再写一个理论模型,而是让 100 个 agent 稳定、可观测、可重试地持续调用 LLM。这里第一批要处理的问题就是 Key 管理和 Base URL 统一。
多 agent 批量调用和单轮问答完全不同。单轮问答里,一个 Key、一个 base_url、一次 request 就能结束;100 个 agent 连续 26 周、每周多轮决策时,调用量会变成数千到数万次并发请求的累积。每个 agent 都可能带自己的记忆摘要、库存、价格表、工资记录和现金余额,这些内容会以不同长度进入 prompt,导致 Token 消耗波动极大。如果 Key 写死在代码里,或者每个脚本各写一份 base_url,后续做 91 次有效运行时会非常痛苦:一次 Key 轮换要改几十个文件,一次模型切换要重新排查所有环境,一次并发超时又无法判断是本地框架问题还是供应商返回问题。把 Key 和 Base URL 统一到环境变量,是让实验可复现的第一道工程化动作。
TaoToken 的定位很明确:提供 Key 与 Base URL。也就是说,你仍然需要自己实现 agent 的记忆、决策解析、市场撮合、工资调整、菜单重定价和随机现金转移。TaoToken 不会替你决定一个店主 agent 是否涨价,也不会替研究代码判断货币是否停止流动。它解决的是“100 个 agent 如何稳定地访问模型”。因此本文的代码会围绕三件事展开:第一,用环境变量注入TAOTOKEN_API_KEY与TAOTOKEN_BASE_URL;第二,用异步并发和信号量控制 100 个 agent 的调用节奏;第三,把每周货币流动、工资响应、菜单调价和随机现金转移写成对照表,方便和 26 周后的停滞现象做比对。
如果你之前用 Claude Code 或 Codex 做代码实验,建议先别急着改研究框架,而是先把工具链配置拆清楚。Claude Code 走settings.json和ANTHROPIC_*变量,Codex 走config.toml和TAOTOKEN_API_KEY这类环境变量,二者不要混用。CC Switch 可以作为供应商切换层,把 TaoToken 的 Base URL 和 Key 同步到不同工具。这样你在跑 100 个 agent 的 Python 模拟时,也能用 Claude Code 辅助读日志,用 Codex 检查配置,而不是在一个 Key 失效时全链路停摆。准备批量运行前,再访问一次 TaoToken 官网 确认 Key 状态和可用模型,避免跑到第 13 周才发现配额或模型权限有问题。
2. 模拟循环的最小可复现结构:记忆、地理、市场与每周指标
要把 Pokhara Lakeside 小镇经济跑成可复现实验,最好先把模拟循环拆成稳定接口。不要一上来就写 100 个 agent 的完整 prompt,而是先定义每周状态、每个 agent 的观察输入、模型返回的决策结构,以及实验结束后要落表的指标。这样做的好处是:当 Token 消耗异常或某周货币流动突然下降时,你可以逐层排查,而不是在一大段 prompt 里猜问题。
一个最小结构可以这样划分:
- 地理层:Pokhara Lakeside 的位置、商业区、居民区、游客路径、随机现金转移节点。
- Agent 层:100 个带记忆的 LLM agent,每个 agent 有角色、现金、库存、工资、价格、最近决策摘要。
- 记忆层:本地保存每个 agent 的历史摘要,不要把全部历史原样塞进 prompt。
- 市场层:商业收入、工资支付、菜单重定价、游客冲击、随机现金转移。
- 调用层:通过 TaoToken Base URL 访问模型,记录每次请求的 token 用量、延迟、重试次数。
- 指标层:按周输出货币流动、平均工资、工资响应、菜单调价比例、随机现金转移消耗比例。
每周指标建议至少包含下面字段,后续可以直接导出 CSV 或 SQLite:
week,run_id,money_flow,avg_wage,wage_response,menu_price_changes,menu_total,random_transfer_spent,random_transfer_total,llm_calls,prompt_tokens,completion_tokens 1,run_001,12000,3100,1.00,2,3981,0,311,1800,920000,145000 2,run_001,11850,3105,1.02,3,3981,12,311,1820,935000,148000 3,run_001,11720,3110,1.03,1,3981,25,311,1790,918000,142000注意,这里的数字只是表结构示例,不是要求你照搬。真正要复现的是每周变化趋势,而不是固定值。尤其是货币流动、工资响应、菜单重定价和随机现金转移,这四类指标要分开记录。很多多 agent 实验失败,不是因为模型不会决策,而是因为日志只记录了“结果”,没有记录“过程”。当 26 周后货币停止流动时,你需要回看是工资没有变化、菜单没有调价、agent 不愿意花钱,还是记忆摘要把现金余额覆盖了。
在 Python 侧,可以先写一个不调用模型的 dry run,确认每周循环、agent 状态更新和指标落表都能跑通。确认后再把模型决策接进来。下面是一个简化骨架,重点看环境变量和落表方式:
import os import csv from pathlib import Path FIELDS = [ "week", "run_id", "money_flow", "avg_wage", "wage_response", "menu_price_changes", "menu_total", "random_transfer_spent", "random_transfer_total", "llm_calls", "prompt_tokens", "completion_tokens", ] def append_week_metrics(path, row): path = Path(path) exists = path.exists() with path.open("a", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=FIELDS) if not exists: writer.writeheader() writer.writerow(row) def run_week(week, agents, market, run_id): # 这里放你的市场撮合、工资调整、菜单重定价、随机现金转移逻辑 # 然后把每周观测整理成 row row = { "week": week, "run_id": run_id, "money_flow": market["money_flow"], "avg_wage": market["avg_wage"], "wage_response": market["wage_response"], "menu_price_changes": market["menu_price_changes"], "menu_total": market["menu_total"], "random_transfer_spent": market["random_transfer_spent"], "random_transfer_total": market["random_transfer_total"], "llm_calls": market["llm_calls"], "prompt_tokens": market["prompt_tokens"], "completion_tokens": market["completion_tokens"], } append_week_metrics(f"outputs/{run_id}_weekly.csv", row)这段代码不调用 TaoToken,但它确定了实验的“产出边界”。一旦你开始接 100 个 agent,模型调用层只负责把观察变成决策,不应该把实验状态写回全局变量。每个 agent 的记忆、现金和价格都应在本地状态里维护。模型返回的 JSON 需要校验,比如要求它输出{action, amount, price, wage, reason},再用本地规则做边界裁剪。这样即使某个 agent 返回了超出库存的购买量,也不会污染整个小镇经济。
另外,26 周、91 次有效运行意味着你需要给每次运行分配唯一run_id。不要用时间戳当唯一标识,否则难以对照。可以用run_001、run_002这样的编号,并在配置文件中记录随机种子、模型 ID、并发数、每轮最大 Token 数。复现实验时,先固定种子和模型,再比较不同并发策略对 Token 消耗的影响。TaoToken 的 Key 和 Base URL 只是访问入口,实验可复现性仍取决于你的状态管理和日志粒度。
3. 用环境变量注入 TaoToken:100 个 agent 的并发调用骨架
多 agent 批量调用最忌讳把 Key 写进代码。推荐的做法是:在 shell 或 CI 环境中注入TAOTOKEN_API_KEY和TAOTOKEN_BASE_URL,代码只读环境变量。Base URL 固定为https://taotoken.net/api,Key 使用占位符YOUR_API_KEY替换。这样你在本地、容器、远程开发机之间迁移时,不需要改任何业务代码。准备创建 Key 时,可以直接进入 TaoToken 控制台 API Keys 页面 创建和管理,但代码里只保留环境变量名。
先设置环境变量:
export TAOTOKEN_API_KEY="YOUR_API_KEY" export TAOTOKEN_BASE_URL="https://taotoken.net/api" export TAOTOKEN_MODEL="你的模型ID"如果你使用 OpenAI 兼容 SDK,可以这样初始化客户端。注意这里的base_url来自环境变量,不要在每个 agent 里重复创建客户端;可以全局共享一个异步客户端,减少连接开销。
import os import json import asyncio from openai import AsyncOpenAI API_KEY = os.environ["TAOTOKEN_API_KEY"] BASE_URL = os.environ["TAOTOKEN_BASE_URL"] MODEL = os.environ.get("TAOTOKEN_MODEL", "YOUR_MODEL_ID") client = AsyncOpenAI( api_key=API_KEY, base_url=BASE_URL, timeout=60.0, max_retries=3, ) async def agent_decision(agent, observation, semaphore): async with semaphore: messages = [ { "role": "system", "content": ( "你是一个小镇经济模拟中的角色。" "你只能返回 JSON,不要输出解释性文本。" "字段包括 action、amount、price、wage、reason。" ), }, { "role": "user", "content": json.dumps( { "agent_id": agent["id"], "role": agent["role"], "cash": agent["cash"], "inventory": agent["inventory"], "memory": agent["memory"][-5:], "observation": observation, }, ensure_ascii=False, ), }, ] response = await client.chat.completions.create( model=MODEL, messages=messages, temperature=0.7, max_tokens=512, ) content = response.choices[0].message.content usage = response.usage return { "agent_id": agent["id"], "content": content, "prompt_tokens": getattr(usage, "prompt_tokens", 0), "completion_tokens": getattr(usage, "completion_tokens", 0), }100 个 agent 不能无限制同时发请求。即使 TaoToken 侧可以承受,你的本地事件循环、网络连接和日志系统也可能成为瓶颈。建议用asyncio.Semaphore控制并发,例如 10 到 30 之间起步,再根据延迟和错误率调整。并发太高会出现 429 或超时,并发太低会让 26 周模拟拖得很长。下面是一个批量调用示例:
async def run_agents_for_one_week(agents, observations, concurrency=20): semaphore = asyncio.Semaphore(concurrency) tasks = [ agent_decision(agent, obs, semaphore) for agent, obs in zip(agents, observations) ] results = await asyncio.gather(*tasks, return_exceptions=True) decisions = [] errors = [] for item in results: if isinstance(item, Exception): errors.append(str(item)) else: decisions.append(item) return decisions, errors这段代码有三个关键点。第一,每个 agent 的 observation 是独立构造的,不要把 100 个 agent 的完整状态一次性塞给一个模型,否则 Token 会爆炸。第二,模型返回后要做 JSON 解析和字段校验,解析失败时不要直接终止整周,而是把该 agent 标记为“本周保持原决策”,并记录错误。第三,token 用量要按 agent、周、run_id 记录,后面才能分析 2.44M 次决策级别的消耗来自哪里。
如果你需要在多个实验之间切换 Key,建议使用 Key 别名而不是硬编码。例如在本地配置文件中维护:
export TAOTOKEN_API_KEY_RESEARCH="YOUR_API_KEY" export TAOTOKEN_API_KEY_DEV="YOUR_API_KEY"然后在启动脚本里选择:
export TAOTOKEN_API_KEY="$TAOTOKEN_API_KEY_RESEARCH"这样既能避免 Key 泄露到代码仓库,也能在批量运行前快速切换。TaoToken 官网提供了 Key 管理入口,建议在每次 26 周长跑前检查 Key 是否有效、配额是否足够、模型是否可用。你可以从 TaoToken 官网 进入控制台,但代码中不要写入真实 Key。
4. Claude Code / Codex / CC Switch 三件套:settings.json 与 config.toml 分开写
很多开发者会在实验过程中同时使用 Claude Code 和 Codex。Claude Code 适合读代码、改配置、解释日志,Codex 适合做终端任务和代码检查。它们连接 TaoToken 的方式不同,配置不能混用。记住一条硬规则:Claude Code 用ANTHROPIC_*变量和settings.json;Codex 用config.toml和独立的环境变量。不要把ANTHROPIC_*套到 Codex,也不要把 Codex 的model_provider写进 Claude Code 的 settings.json。
Claude Code 的配置文件通常放在~/.claude/settings.json。下面是一个示例,把 Base URL 指向https://taotoken.net/api,Key 用YOUR_API_KEY占位。模型 ID 请按你在 TaoToken 控制台看到的可用模型替换。
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_AUTH_TOKEN": "YOUR_API_KEY", "ANTHROPIC_MODEL": "claude-3-5-sonnet-20241022", "ANTHROPIC_SMALL_FAST_MODEL": "claude-3-5-haiku-20241022" } }改完后重启 Claude Code,或在终端重新加载配置。验证时不要直接跑长任务,先问一个简单问题,确认请求能到达 TaoToken。如果出现 401,优先检查ANTHROPIC_AUTH_TOKEN是否被 shell 里的旧变量覆盖;如果出现 404,检查 Base URL 是否多写了/v1或结尾斜杠。
Codex 的配置文件通常放在~/.codex/config.toml。下面是一个供应商配置示例,重点是把base_url指向 TaoToken,并通过env_key读取TAOTOKEN_API_KEY。不要在 Codex 里使用ANTHROPIC_BASE_URL。
model = "YOUR_MODEL_ID" model_provider = "taotoken" [model_providers.taotoken] name = "TaoToken" base_url = "https://taotoken.net/api" env_key = "TAOTOKEN_API_KEY"然后在 shell 中设置:
export TAOTOKEN_API_KEY="YOUR_API_KEY"启动 Codex 前,可以用env | grep TAOTOKEN确认变量存在。如果 Codex 仍然读取旧配置,检查是否同时存在多个配置文件,或者环境变量名写错。Codex 的 TOML 对大小写和字段层级敏感,model_providers下的子表名要和model_provider的值一致。
CC Switch 可以作为“三件套”的切换层:Claude Code、Codex、以及 CC Switch 自身的供应商列表。推荐流程是:在 CC Switch 中新增一个供应商,名称填TaoToken,Base URL 填https://taotoken.net/api,API Key 填YOUR_API_KEY,然后分别同步到 Claude Code 和 Codex。同步后,Claude Code 侧应生成ANTHROPIC_*配置,Codex 侧应生成config.toml与对应环境变量。你可以在 CC Switch 中维护多套配置,例如“研究长跑”“日常开发”“代码审查”,但每套都只保存 Key 别名,不要把真实 Key 提交到仓库。
如果你使用 CC Switch 的 JSON 配置,可以按类似字段填写,具体以工具当前版本为准:
{ "provider": "taotoken", "name": "TaoToken", "base_url": "https://taotoken.net/api", "api_key": "YOUR_API_KEY", "note": "用于 100 agent 小镇经济模拟" }配置完成后,回到 Python 模拟项目,用同一套环境变量启动批量运行。Claude Code 和 Codex 只是辅助工具,不参与 agent 决策循环。这样职责清晰:TaoToken 提供 Key 与 Base URL,CC Switch 负责切换,Claude Code 负责代码与日志,Codex 负责终端与配置检查,你的实验框架负责记忆、市场和行为规则。
5. 26 周 Token 消耗观测:Key 管理、限流、重试与成本切片
100 个 agent、26 周、91 次有效运行,意味着你面对的不是“几次请求”,而是持续数天甚至数周的批量调用。Token 消耗会集中在几个地方:每个 agent 的记忆摘要、每周观察、模型返回的决策 JSON、重试请求、以及解析失败后的二次请求。如果每次调用都把完整历史塞进去,prompt token 会迅速增长。建议把每个 agent 的记忆压缩成结构化摘要,例如只保留最近 5 条决策、当前现金档位、库存档位、价格趋势和工资趋势。不要把 26 周的全部对话原样保留。
一个实用的 Token 预算表可以按周记录:
run_id,week,agent_count,llm_calls,prompt_tokens,completion_tokens,total_tokens,retry_count,error_count,avg_latency_ms run_001,1,100,1800,920000,145000,1065000,12,3,840 run_001,2,100,1820,935000,148000,1083000,15,4,860 run_001,3,100,1790,918000,142000,1060000,10,2,820如果某周total_tokens突然翻倍,先检查是不是某个 agent 的记忆摘要没有截断,或者模型返回了超长解释。如果retry_count升高,检查并发数和网络延迟。如果error_count集中在同一类 agent,检查 prompt 是否触发了模型拒答或 JSON 解析失败。TaoToken 侧负责 Key 与 Base URL,不会替你判断 prompt 质量,因此批量实验必须自己记录这些维度。
Key 管理建议分三层:
- 开发 Key:用于单次调试和少量 agent 测试,不跑 26 周长任务。
- 研究 Key:用于批量运行,单独设置并发和配额告警,避免被其他脚本占用。
- 备份 Key:只在研究 Key 失效或轮换时启用,不参与日常自动任务。
在 TaoToken 控制台中创建 Key 后,不要写进.py文件、Jupyter Notebook 或 Git 仓库。可以使用.env文件,但必须把.env加入.gitignore。在容器中运行时,用环境变量注入,而不是把 Key 挂载到镜像层。每次长跑前,先执行一个最小探活请求,确认 Key、Base URL 和模型 ID 三者匹配。
限流和重试策略也很关键。异步调用时,遇到 429 不要立即无限重试,而是使用指数退避。下面是一个重试装饰器示例:
import asyncio import random async def call_with_backoff(func, *args, max_attempts=5, **kwargs): for attempt in range(max_attempts): try: return await func(*args, **kwargs) except Exception as exc: if attempt == max_attempts - 1: raise wait = min(2 ** attempt + random.random(), 30) await asyncio.sleep(wait) raise RuntimeError("unreachable")把并发信号量、超时和退避组合起来,才能让 100 个 agent 在 26 周里稳定推进。建议先跑 3 周小规模实验,观察每周 Token 曲线、错误率和指标变化,再扩大到 91 次有效运行。TaoToken 官网提供了 Coding Plan 与 Key 管理入口,长跑前可以从 TaoToken 官网 了解适合批量调用的方案,但不要在没有小规模验证的情况下直接跑满 26 周。
6. 常见报错排查:401、429、模型不存在与配置未生效
批量运行中,最常见的错误不是经济模拟本身,而是配置和调用层。下面按错误类型整理排查顺序。所有命令都在本地终端执行,不要跳过最小复现步骤。
401 Unauthorized:通常是 Key 错误、Key 未生效、环境变量被覆盖。检查:
echo "$TAOTOKEN_API_KEY" | wc -c env | grep TAOTOKEN如果输出为空,说明当前 shell 没有注入 Key。如果 Claude Code 报 401,检查~/.claude/settings.json中的ANTHROPIC_AUTH_TOKEN;如果 Codex 报 401,检查TAOTOKEN_API_KEY是否与config.toml的env_key一致。
403 Forbidden:可能是 Key 权限不足或模型未开通。到 TaoToken 控制台确认该 Key 是否允许访问目标模型。不要用开发 Key 跑高并发研究任务。
404 Not Found:Base URL 或路径错误。Python SDK 中应使用https://taotoken.net/api,不要在末尾加/v1,也不要加多余斜杠。Claude Code 的ANTHROPIC_BASE_URL同样填这个值。
429 Too Many Requests:并发太高或短时间请求过密。降低asyncio.Semaphore的并发数,例如从 30 降到 10,并启用指数退避。记录retry_count,如果集中在某几周,检查是否与游客冲击或菜单重定价高峰重合。
模型不存在:模型 ID 写错,或该模型不在当前 Key 的可用列表里。用下面的命令做轻量探活:
curl -sS "https://taotoken.net/api/models" \ -H "Authorization: Bearer $TAOTOKEN_API_KEY"如果返回列表中没有你需要的模型,回到控制台查看可用模型,再更新TAOTOKEN_MODEL。
Claude Code 配置未生效:检查 settings.json 路径是否正确,是否重启了 Claude Code,是否在项目目录里还有另一份配置覆盖了全局配置。可以用claude --version和claude config list等命令辅助确认。不同版本命令可能不同,以本机帮助为准。
Codex 配置未生效:检查~/.codex/config.toml的 TOML 语法,尤其是[model_providers.taotoken]的层级。确认model_provider的值与子表名一致,确认env_key指向的环境变量已导出。不要在 Codex 中使用ANTHROPIC_*。
超时或连接中断:先降低并发,再检查本地网络和 DNS。不要依赖任何非正规网络手段,也不要把生产数据库或 Oracle 直连到 agent 循环中。所有 SQL 和命令都应在本地或独立测试环境执行。模拟实验的数据落盘到本地 CSV、SQLite 或实验数据库,不要从 agent 直接连生产库。
排查时遵循“先最小请求,再批量;先单 agent,再多 agent;先单周,再多周”的顺序。很多看似复杂的问题,最后只是环境变量没导出或 Base URL 多了一个斜杠。
7. 从模型对话到 Claude Code 文档:按顺序完成 TaoToken 接入
如果你已经准备复现 100 个 agent 的 Pokhara Lakeside 小镇经济,建议按下面顺序完成 TaoToken 接入,而不是一次性把所有工具都配满。
第一步,先到模型对话页面验证模型可用性。你可以直接进入 模型对话 试一个简单请求,确认 Key、Base URL 和模型 ID 能正常返回。这个步骤能排除大部分鉴权和模型权限问题。
第二步,了解适合批量调用的方案。100 个 agent、26 周、91 次有效运行的 Token 消耗不低,建议在 Coding Plan 页面确认当前方案是否满足并发与配额需求。不要等到第 20 周才发现额度不足。
第三步,创建和管理 Key。进入 API Keys 创建研究专用 Key,并设置好环境变量。记住,代码中只出现YOUR_API_KEY占位符,真实 Key 只放在本地环境或密钥管理服务中。
第四步,配置 Claude Code 或 Codex 辅助开发。Claude Code 的完整配置方式可以参考 Claude Code 文档。如果你使用 Codex,则按config.toml单独配置,不要混用ANTHROPIC_*。CC Switch 可以作为中间层同步供应商,但最终仍要确认每个工具读取的 Base URL 都是https://taotoken.net/api。
完成这四步后,再回到 Python 模拟项目。用环境变量启动 100 个 agent,先跑 1 周,再跑 3 周,最后扩展到 26 周。每周输出货币流动、工资响应、菜单调价和随机现金转移对照表。只有当调用层稳定、Key 管理清晰、日志完整时,你才有机会复现“货币停止流动”这类宏观现象,而不是把工程问题误判为经济行为。TaoToken 提供 Key 与 Base URL,实验框架、记忆设计、市场规则和指标分析仍然需要你自己完成。准备开始长跑前,可以从 TaoToken 官网 做最后一次配置确认。