{
  "canonical_name": "xingjianll/cyclic-agent",
  "compilation_id": "pack_1622fd86b93d4301b742dbd34bee4ca9",
  "created_at": "2026-05-20T06:06:07.288226+00:00",
  "created_by": "project-pack-compiler",
  "feedback": {
    "carrier_selection_notes": [
      "viable_asset_types=prompt, recipe, host_instruction, eval, preflight",
      "recommended_asset_types=prompt, recipe, host_instruction, eval, preflight"
    ],
    "evidence_delta": {
      "confirmed_claims": [
        "identity_anchor_present",
        "capability_and_host_targets_present",
        "install_path_declared_or_better"
      ],
      "missing_required_fields": [],
      "must_verify_forwarded": [
        "Run or inspect `pip install cyclic-agent` in an isolated environment.",
        "Confirm the project exposes the claimed capability to at least one target host."
      ],
      "quickstart_execution_scope": "allowlisted_sandbox_smoke",
      "sandbox_command": "pip install cyclic-agent",
      "sandbox_container_image": "python:3.12-slim",
      "sandbox_execution_backend": "docker",
      "sandbox_planner_decision": "deterministic_isolated_install",
      "sandbox_validation_id": "sbx_ec4d28e7331f4ab29eff4ea2d044a62e"
    },
    "feedback_event_type": "project_pack_compilation_feedback",
    "learning_candidate_reasons": [],
    "template_gaps": []
  },
  "identity": {
    "canonical_id": "project_807a9f098eaa329a58360f6ca6ac5931",
    "canonical_name": "xingjianll/cyclic-agent",
    "homepage_url": null,
    "license": "unknown",
    "repo_url": "https://github.com/xingjianll/cyclic-agent",
    "slug": "cyclic-agent",
    "source_packet_id": "phit_dcd6584716d649bda59363c11e67b8f5",
    "source_validation_id": "dval_5d1a5684881840c7a9f8cecb96cb914a"
  },
  "merchandising": {
    "best_for": "需要软件开发与交付能力，并使用 local_cli的用户",
    "github_forks": null,
    "github_stars": null,
    "one_liner_en": "<div align= \"center\">",
    "one_liner_zh": "<div align= \"center\">",
    "primary_category": {
      "category_id": "software-development",
      "confidence": "medium",
      "name_en": "Software Development",
      "name_zh": "软件开发与交付",
      "reason": "matched_keywords:git, cli"
    },
    "target_user": "使用 local_cli 等宿主 AI 的用户",
    "title_en": "cyclic-agent",
    "title_zh": "cyclic-agent 能力包",
    "visible_tags": [
      {
        "label_en": "Visual Generation",
        "label_zh": "视觉生成",
        "source": "repo_evidence_project_characteristics",
        "tag_id": "product_domain-visual-generation",
        "type": "product_domain"
      },
      {
        "label_en": "Visual Workflow Orchestration",
        "label_zh": "视觉工作流编排",
        "source": "repo_evidence_project_characteristics",
        "tag_id": "user_job-visual-workflow-orchestration",
        "type": "user_job"
      },
      {
        "label_en": "Durable Memory",
        "label_zh": "长期记忆",
        "source": "repo_evidence_project_characteristics",
        "tag_id": "core_capability-durable-memory",
        "type": "core_capability"
      },
      {
        "label_en": "Checkpoint Resume",
        "label_zh": "断点恢复流程",
        "source": "repo_evidence_project_characteristics",
        "tag_id": "workflow_pattern-checkpoint-resume",
        "type": "workflow_pattern"
      },
      {
        "label_en": "Plugin Ecosystem",
        "label_zh": "插件生态",
        "source": "repo_evidence_project_characteristics",
        "tag_id": "selection_signal-plugin-ecosystem",
        "type": "selection_signal"
      }
    ]
  },
  "packet_id": "phit_dcd6584716d649bda59363c11e67b8f5",
  "page_model": {
    "artifacts": {
      "artifact_slug": "cyclic-agent",
      "files": [
        "PROJECT_PACK.json",
        "QUICK_START.md",
        "PROMPT_PREVIEW.md",
        "HUMAN_MANUAL.md",
        "AI_CONTEXT_PACK.md",
        "BOUNDARY_RISK_CARD.md",
        "PITFALL_LOG.md",
        "REPO_INSPECTION.json",
        "REPO_INSPECTION.md",
        "CAPABILITY_CONTRACT.json",
        "EVIDENCE_INDEX.json",
        "CLAIM_GRAPH.json"
      ],
      "required_files": [
        "PROJECT_PACK.json",
        "QUICK_START.md",
        "PROMPT_PREVIEW.md",
        "HUMAN_MANUAL.md",
        "AI_CONTEXT_PACK.md",
        "BOUNDARY_RISK_CARD.md",
        "PITFALL_LOG.md",
        "REPO_INSPECTION.json"
      ]
    },
    "detail": {
      "capability_source": "Project Hit Packet + DownstreamValidationResult",
      "commands": [
        {
          "command": "pip install cyclic-agent",
          "label": "Python / pip · 官方安装入口",
          "source": "https://github.com/xingjianll/cyclic-agent#readme",
          "verified": true
        }
      ],
      "display_tags": [
        "视觉生成",
        "视觉工作流编排",
        "长期记忆",
        "断点恢复流程",
        "插件生态"
      ],
      "eyebrow": "软件开发与交付",
      "glance": [
        {
          "body": "判断自己是不是目标用户。",
          "label": "最适合谁",
          "value": "需要软件开发与交付能力，并使用 local_cli的用户"
        },
        {
          "body": "先理解能力边界，再决定是否继续。",
          "label": "核心价值",
          "value": "<div align= \"center\">"
        },
        {
          "body": "未完成验证前保持审慎。",
          "label": "继续前",
          "value": "publish to Doramagic.ai project surfaces"
        }
      ],
      "guardrail_source": "Boundary & Risk Card",
      "guardrails": [
        {
          "body": "Prompt Preview 只展示流程，不证明项目已安装或运行。",
          "label": "Check 1",
          "value": "不要把试用当真实运行"
        },
        {
          "body": "local_cli",
          "label": "Check 2",
          "value": "确认宿主兼容"
        },
        {
          "body": "publish to Doramagic.ai project surfaces",
          "label": "Check 3",
          "value": "先隔离验证"
        }
      ],
      "mode": "prompt, recipe, host_instruction, eval, preflight",
      "pitfall_log": {
        "items": [
          {
            "body": "README/documentation is current enough for a first validation pass.",
            "category": "能力坑",
            "evidence": [
              "capability.assumptions | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | README/documentation is current enough for a first validation pass."
            ],
            "severity": "medium",
            "suggested_check": "将假设转成下游验证清单。",
            "title": "能力判断依赖假设",
            "user_impact": "假设不成立时，用户拿不到承诺的能力。"
          },
          {
            "body": "未记录 last_activity_observed。",
            "category": "维护坑",
            "evidence": [
              "evidence.maintainer_signals | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | last_activity_observed missing"
            ],
            "severity": "medium",
            "suggested_check": "补 GitHub 最近 commit、release、issue/PR 响应信号。",
            "title": "维护活跃度未知",
            "user_impact": "新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。"
          },
          {
            "body": "no_demo",
            "category": "安全/权限坑",
            "evidence": [
              "downstream_validation.risk_items | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | no_demo; severity=medium"
            ],
            "severity": "medium",
            "suggested_check": "进入安全/权限治理复核队列。",
            "title": "下游验证发现风险项",
            "user_impact": "下游已经要求复核，不能在页面中弱化。"
          },
          {
            "body": "no_demo",
            "category": "安全/权限坑",
            "evidence": [
              "risks.scoring_risks | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | no_demo; severity=medium"
            ],
            "severity": "medium",
            "suggested_check": "把风险写入边界卡，并确认是否需要人工复核。",
            "title": "存在评分风险",
            "user_impact": "风险会影响是否适合普通用户安装。"
          },
          {
            "body": "issue_or_pr_quality=unknown。",
            "category": "维护坑",
            "evidence": [
              "evidence.maintainer_signals | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | issue_or_pr_quality=unknown"
            ],
            "severity": "low",
            "suggested_check": "抽样最近 issue/PR，判断是否长期无人处理。",
            "title": "issue/PR 响应质量未知",
            "user_impact": "用户无法判断遇到问题后是否有人维护。"
          },
          {
            "body": "release_recency=unknown。",
            "category": "维护坑",
            "evidence": [
              "evidence.maintainer_signals | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | release_recency=unknown"
            ],
            "severity": "low",
            "suggested_check": "确认最近 release/tag 和 README 安装命令是否一致。",
            "title": "发布节奏不明确",
            "user_impact": "安装命令和文档可能落后于代码，用户踩坑概率升高。"
          }
        ],
        "source": "ProjectPitfallLog + ProjectHitPacket + validation + community signals",
        "summary": "发现 6 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：能力坑 - 能力判断依赖假设。",
        "title": "踩坑日志"
      },
      "snapshot": {
        "contributors": null,
        "forks": null,
        "license": "unknown",
        "note": "站点快照，非实时质量证明；用于开工前背景判断。",
        "stars": null
      },
      "source_url": "https://github.com/xingjianll/cyclic-agent",
      "steps": [
        {
          "body": "不安装项目，先体验能力节奏。",
          "code": "preview",
          "title": "先试 Prompt"
        },
        {
          "body": "理解输入、输出、失败模式和边界。",
          "code": "manual",
          "title": "读说明书"
        },
        {
          "body": "把上下文交给宿主 AI 继续工作。",
          "code": "context",
          "title": "带给 AI"
        },
        {
          "body": "进入主力环境前先完成安装入口与风险边界验证。",
          "code": "verify",
          "title": "沙箱验证"
        }
      ],
      "subtitle": "<div align= \"center\">",
      "title": "cyclic-agent 能力包",
      "trial_prompt": "# cyclic-agent - Prompt Preview\n\n> 复制下面这段 Prompt 到你常用的 AI，先试一次，不需要安装。\n> 它的目标是让你直接体验这个项目的服务方式，而不是阅读项目介绍。\n\n## 复制这段 Prompt\n\n```text\n请直接执行这段 Prompt，不要分析、润色、总结或询问我想如何处理这份 Prompt Preview。\n\n你现在扮演 cyclic-agent 的“安装前体验版”。\n这不是项目介绍、不是评价报告、不是 README 总结。你的任务是让我用最小成本体验它的核心服务。\n\n我的试用任务：我想用它完成一个真实的软件开发与交付任务。\n我常用的宿主 AI：Local CLI\n\n【体验目标】\n围绕我的真实任务，现场演示这个项目如何把输入转成 示例引导, 判断线索。重点是让我感受到工作方式，而不是给我项目背景。\n\n【业务流约束】\n- 你必须像一个正在提供服务的项目能力包，而不是像一个讲解员。\n- 每一轮只推进一个步骤；提出问题后必须停下来等我回答。\n- 每一步都必须让我感受到一个具体服务动作：澄清、整理、规划、检查、判断或收尾。\n- 每一步都要说明：当前目标、你需要我提供什么、我回答后你会产出什么。\n- 不要安装、不要运行命令、不要写代码、不要声称测试通过、不要声称已经修改文件。\n- 需要真实安装或宿主加载后才能验证的内容，必须明确说“这一步需要安装后验证”。\n- 如果我说“用示例继续”，你可以用虚构示例推进，但仍然不能声称真实执行。\n\n【可体验服务能力】\n- 安装前能力预览: <div align= \"center\"> 输入：用户任务, 当前 AI 对话上下文；输出：示例引导, 判断线索。\n\n【必须安装后才可验证的能力】\n- 命令行启动或安装流程: 项目文档中存在可执行命令，真实使用需要在本地或宿主环境中运行这些命令。 输入：终端环境, 包管理器, 项目依赖；输出：安装结果, 列表/更新/运行结果。\n\n【核心服务流】\n请严格按这个顺序带我体验。不要一次性输出完整流程：\n1. page-1：项目介绍。围绕“项目介绍”模拟一次用户任务，不展示安装或运行结果。\n2. page-2：安装与依赖。围绕“安装与依赖”模拟一次用户任务，不展示安装或运行结果。\n3. page-3：快速入门指南。围绕“快速入门指南”模拟一次用户任务，不展示安装或运行结果。\n4. page-4：State基类设计。围绕“State基类设计”模拟一次用户任务，不展示安装或运行结果。\n5. page-5：CyclicExecutor执行器。围绕“CyclicExecutor执行器”模拟一次用户任务，不展示安装或运行结果。\n\n【核心能力体验剧本】\n每一步都必须按“输入 -> 服务动作 -> 中间产物”执行。不要只说流程名：\n1. page-1\n输入：用户提供的“项目介绍”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n2. page-2\n输入：用户提供的“安装与依赖”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n3. page-3\n输入：用户提供的“快速入门指南”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n4. page-4\n输入：用户提供的“State基类设计”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n5. page-5\n输入：用户提供的“CyclicExecutor执行器”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n【项目服务规则】\n这些规则决定你如何服务用户。不要解释规则本身，而要在每一步执行时遵守：\n- 先确认用户任务、输入材料和成功标准，再模拟项目能力。\n- 每一步都必须形成可检查的小产物，并等待用户确认后再继续。\n- 凡是需要安装、调用工具或访问外部服务的能力，都必须标记为安装后验证。\n\n【每一步的服务约束】\n- Step 1 / page-1：Step 1 必须围绕“项目介绍”形成一个小中间产物，并等待用户确认。\n- Step 2 / page-2：Step 2 必须围绕“安装与依赖”形成一个小中间产物，并等待用户确认。\n- Step 3 / page-3：Step 3 必须围绕“快速入门指南”形成一个小中间产物，并等待用户确认。\n- Step 4 / page-4：Step 4 必须围绕“State基类设计”形成一个小中间产物，并等待用户确认。\n- Step 5 / page-5：Step 5 必须围绕“CyclicExecutor执行器”形成一个小中间产物，并等待用户确认。\n\n【边界与风险】\n- 不要声称已经安装、运行、调用 API、读写本地文件或完成真实任务。\n- 安装前预览只能展示工作方式，不能证明兼容性、性能或输出质量。\n- 涉及安装、插件加载、工具调用或外部服务的能力必须安装后验证。\n\n【可追溯依据】\n这些路径只用于你内部校验或在我追问“依据是什么”时简要引用。不要在首次回复主动展开：\n- https://github.com/xingjianll/cyclic-agent#readme\n- README.md\n- cyclic_agent/__init__.py\n- pyproject.toml\n- examples/hello_world/hello_world.py\n- cyclic_agent/executor.py\n- cyclic_agent/state.py\n\n【首次问题规则】\n- 首次三问必须先确认用户目标、成功标准和边界，不要提前进入工具、安装或实现细节。\n- 如果后续需要技术条件、文件路径或运行环境，必须等用户确认目标后再追问。\n\n首次回复必须只输出下面 4 个部分：\n1. 体验开始：用 1 句话说明你将带我体验 cyclic-agent 的核心服务。\n2. 当前步骤：明确进入 Step 1，并说明这一步要解决什么。\n3. 你会如何服务我：说明你会先改变我完成任务的哪个动作。\n4. 只问我 3 个问题，然后停下等待回答。\n\n首次回复禁止输出：后续完整流程、证据清单、安装命令、项目评价、营销文案、已经安装或运行的说法。\n\nStep 1 / brainstorming 的二轮协议：\n- 我回答首次三问后，你仍然停留在 Step 1 / brainstorming，不要进入 Step 2。\n- 第二次回复必须产出 6 个部分：澄清后的任务定义、成功标准、边界条件、\n  2-3 个可选方案、每个方案的权衡、推荐方案。\n- 第二次回复最后必须问我是否确认推荐方案；只有我明确确认后，才能进入下一步。\n- 第二次回复禁止输出 git worktree、代码计划、测试文件、命令或真实执行结果。\n\n后续对话规则：\n- 我回答后，你先完成当前步骤的中间产物并等待确认；只有我确认后，才能进入下一步。\n- 每一步都要生成一个小的中间产物，例如澄清后的目标、计划草案、测试意图、验证清单或继续/停止判断。\n- 所有演示都写成“我会建议/我会引导/这一步会形成”，不要写成已经真实执行。\n- 不要声称已经测试通过、文件已修改、命令已运行或结果已产生。\n- 如果某个能力必须安装后验证，请直接说“这一步需要安装后验证”。\n- 如果证据不足，请明确说“证据不足”，不要补事实。\n```\n",
      "voices": [
        {
          "body": "来源平台：reddit。reddit: AI agents as finite state machine ? : r/LocalLLaMA - Reddit（https://www.reddit.com/r/LocalLLaMA/comments/1hv11ud/ai_agents_as_finite_state_machine/）。这些是项目级外部声音，不作为单独质量证明。",
          "items": [
            {
              "kind": "searxng_indexed",
              "source": "reddit",
              "title": "AI agents as finite state machine ? : r/LocalLLaMA - Reddit",
              "url": "https://www.reddit.com/r/LocalLLaMA/comments/1hv11ud/ai_agents_as_finite_state_machine/"
            }
          ],
          "status": "已收录 1 条来源",
          "title": "社区讨论"
        }
      ]
    },
    "homepage_card": {
      "category": "软件开发与交付",
      "desc": "<div align= \"center\">",
      "effort": "安装已验证",
      "forks": null,
      "icon": "code",
      "name": "cyclic-agent 能力包",
      "risk": "需复核",
      "slug": "cyclic-agent",
      "stars": null,
      "tags": [
        "视觉生成",
        "视觉工作流编排",
        "长期记忆",
        "断点恢复流程",
        "插件生态"
      ],
      "thumb": "gray",
      "type": "Prompt Preview"
    },
    "manual": {
      "markdown": "# https://github.com/xingjianll/cyclic-agent 项目说明书\n\n生成时间：2026-05-20 05:59:53 UTC\n\n## 目录\n\n- [项目介绍](#page-1)\n- [安装与依赖](#page-2)\n- [快速入门指南](#page-3)\n- [State基类设计](#page-4)\n- [CyclicExecutor执行器](#page-5)\n- [有限状态机模式](#page-6)\n- [Search状态模块](#page-7)\n- [CoT状态模块](#page-8)\n- [Hello World示例](#page-9)\n- [Bilibili Surfer示例](#page-10)\n\n<a id='page-1'></a>\n\n## 项目介绍\n\n### 相关页面\n\n相关主题：[安装与依赖](#page-2), [State基类设计](#page-4)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [README.md](https://github.com/xingjianll/cyclic-agent/blob/main/README.md)\n- [cyclic_agent/__init__.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/__init__.py)\n- [cyclic_agent/state.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/state.py)\n- [cyclic_agent/executor.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n- [cyclic_agent/search.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/search.py)\n- [cyclic_agent/cot.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/cot.py)\n- [examples/hello_world/hello_world.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/hello_world/hello_world.py)\n- [examples/bilibili_surfer/bilibili_surfer.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n- [examples/bilibili_surfer/fifo.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n</details>\n\n# 项目介绍\n\n## 1 项目概述\n\nCyclicAgent 是一个专为创建 LLM 驱动的完全自主 AI Agent 而设计的框架。该框架的核心创新在于将 Agent 抽象为有限状态机（FSM），采用状态设计模式实现。在每个状态中，Agent 根据内部状态属性（如内存、元提示等）以及外部信号来推断下一个状态，并与外部环境进行交互。\n\n资料来源：[README.md:1-10]()\n\n## 2 核心设计理念\n\n### 2.1 有限状态机架构\n\nCyclicAgent 的核心理念基于有限状态机（FSM）设计。框架中的所有状态都实现了一个状态转换函数，该函数返回另一个状态对象。这种设计允许状态转换操作无限链接，从而使 Agent 变得“循环”。\n\n```mermaid\ngraph TD\n    A[初始状态] --> B[State.next]\n    B --> C{状态转换}\n    C -->|State A| D[执行动作]\n    C -->|State B| E[执行动作]\n    D --> B\n    E --> B\n```\n\n### 2.2 状态设计模式\n\n每个状态（State）都包含一个 `next()` 方法，该方法负责确定下一个要转换到的状态。状态可以携带内部属性，如内存、提示词等，这些属性在状态转换过程中会被保留和传递。\n\n资料来源：[cyclic_agent/state.py:6-9]()\n\n## 3 核心组件\n\n### 3.1 State 基类\n\nState 是框架的基础类，定义在 `cyclic_agent/state.py` 中。所有自定义状态都必须继承此类并实现 `next()` 方法。\n\n```python\nclass State[SigT](BaseModel):\n    @abstractmethod\n    def next(self, signal: SigT | None = None) -> State[SigT]:\n        \"\"\"Transition to the next state.\"\"\"\n        raise NotImplementedError\n```\n\nState 类使用 Pydantic 的 BaseModel 作为基类，提供了数据验证和序列化能力。每个状态都有一个泛型参数 `SigT` 表示信号的接收类型，`next()` 方法接收一个可选的信号参数并返回下一个状态。\n\n资料来源：[cyclic_agent/state.py:1-10]()\n\n### 3.2 CyclicExecutor 执行器\n\nCyclicExecutor 负责执行状态机的运行循环，支持暂停、恢复和终止操作。\n\n```python\nclass CyclicExecutor:\n    def __init__(self, default_time_interval: float):\n        self.running = False\n        self.lock = threading.Lock()\n        self.default_time_interval = default_time_interval\n        self.killed = False\n        self.thread = None\n```\n\n执行器使用独立线程运行主循环，在每次状态转换后根据 `default_time_interval` 参数进行休眠，实现周期性的状态检查和转换。\n\n资料来源：[cyclic_agent/executor.py:1-33]()\n\n### 3.3 执行器控制方法\n\n| 方法 | 功能描述 | 线程安全 |\n|------|---------|----------|\n| `start(initial_state)` | 启动执行器，传入初始状态 | 是 |\n| `pause()` | 暂停执行循环 | 是 |\n| `resume()` | 恢复执行循环 | 是 |\n| `kill()` | 终止执行器 | 是 |\n\n资料来源：[cyclic_agent/executor.py:11-24]()\n\n### 3.4 预置状态组件\n\n框架提供了两个预置的状态组件用于常见场景：\n\n| 组件 | 文件位置 | 用途 |\n|------|----------|------|\n| Search | `cyclic_agent/search.py` | 执行搜索操作并根据结果转换状态 |\n| CoT | `cyclic_agent/cot.py` | 实现思维链（Chain of Thought）模式 |\n\nSearch 组件允许定义搜索查询和回调函数来根据搜索结果决定后续状态：\n\n```python\nclass Search(State[None]):\n    query: str\n    exit_: Callable[[[Annotated[str, \"search result\"]]], State]\n\n    def next(self, signal: None = None) -> State:\n        search_result = self.search(self.query)\n        return self.exit_(search_result)\n```\n\n资料来源：[cyclic_agent/search.py:1-13]()\n\nCoT 组件实现了思维链模式，通过在提示词后添加\"Let's think step by step.\"来增强 LLM 的推理能力：\n\n```python\nclass CoT(State[None]):\n    exit_: Callable[[str], State]\n    llm: State\n    prompt: str\n\n    def next(self, signal: None = None) -> State:\n        prompt = self.prompt + \"Let's think step by step.\"\n        # ... 回调处理\n```\n\n资料来源：[cyclic_agent/cot.py:1-17]()\n\n## 4 工作流程\n\n### 4.1 状态转换机制\n\nCyclicAgent 的工作流程遵循以下循环：\n\n```mermaid\ngraph LR\n    A[State 实例] -->|调用| B[next 方法]\n    B --> C[执行业务逻辑]\n    C --> D[确定下一状态]\n    D --> E[返回新状态对象]\n    E --> A\n```\n\n1. 用户创建初始状态实例\n2. 将初始状态传递给 CyclicExecutor 的 `start()` 方法\n3. 执行器在新线程中运行主循环\n4. 每次循环调用当前状态的 `next()` 方法\n5. `next()` 方法执行业务逻辑并返回下一个状态\n6. 循环回到步骤 4\n\n资料来源：[cyclic_agent/executor.py:31-35]()\n\n### 4.2 简单示例工作原理\n\n以下是一个最简单的两个状态互相转换的示例：\n\n```python\nclass AskQuestion(State[None]):\n    def next(self, signal: None = None) -> AnswerQuestion:\n        response = co.chat(message=\"Ask a question\")\n        return AnswerQuestion(question=response.text)\n\nclass AnswerQuestion(State[None]):\n    question: str\n    def next(self, signal: None = None) -> AskQuestion:\n        answer = co.chat(message=self.question)\n        return AskQuestion()\n\n# 启动执行器\nexecutor = CyclicExecutor(5)  # 5秒间隔\nexecutor.start(AskQuestion())\n```\n\n该示例创建了两个状态：AskQuestion 和 AnswerQuestion，它们互相转换形成无限循环。\n\n资料来源：[examples/hello_world/hello_world.py:1-34]()\n\n## 5 内存管理\n\n### 5.1 FIFO 队列\n\n框架通过 FIFO（先进先出）队列实现内存管理，用于记录 Agent 的历史行为和决策过程。\n\n```python\nclass Fifo:\n    def __init__(self):\n        self.capacity = 100  # 最大容量\n        self.queue = []\n        self.log_file = \"fifo_log.txt\"\n\n    def add(self, item):\n        if len(self.queue) >= self.capacity:\n            self.queue.pop(0)  # 移除最旧的记录\n        self.queue.append((item, timestamp))\n```\n\nFIFO 队列支持：\n- 容量限制：默认最大存储 100 条记录\n- 持久化日志：自动将记录写入文件\n- 时间戳记录：每条记录都附带时间戳\n- 有序检索：按时间顺序显示历史记录\n\n资料来源：[examples/bilibili_surfer/fifo.py:1-31]()\n\n### 5.2 状态继承结构\n\n在实际应用中，状态通常需要继承 `BilibiliStateBase` 等基类来获取内存和 LLM 客户端等共享资源：\n\n```python\nclass BilibiliStateBase(State[None], ABC):\n    model_config = ConfigDict(arbitrary_types_allowed=True)\n    initial_prompt: str\n    memory: Fifo\n    co: Client\n    credential: Credential\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:26-33]()\n\n## 6 包结构\n\n### 6.1 导出接口\n\n框架通过 `cyclic_agent/__init__.py` 对外导出核心接口：\n\n```python\nfrom cyclic_agent.state import State\nfrom cyclic_agent.executor import CyclicExecutor\n\n__all__ = [\"State\", \"CyclicExecutor\"]\n```\n\n用户只需导入 State 基类和 CyclicExecutor 执行器即可开始使用框架。\n\n资料来源：[cyclic_agent/__init__.py:1-6]()\n\n### 6.2 项目目录结构\n\n```\ncyclic-agent/\n├── cyclic_agent/           # 核心框架\n│   ├── __init__.py        # 包初始化，导出公共接口\n│   ├── state.py           # State 基类定义\n│   ├── executor.py        # CyclicExecutor 执行器\n│   ├── search.py          # Search 预置状态\n│   └── cot.py             # CoT 预置状态\n├── examples/              # 示例代码\n│   ├── hello_world/       # 简单示例\n│   └── bilibili_surfer/   # B站冲浪者完整示例\n└── README.md              # 项目文档\n```\n\n## 7 安装与使用\n\n### 7.1 安装方式\n\n通过 pip 安装：\n\n```shell\npip install cyclic-agent\n```\n\n资料来源：[README.md:11-13]()\n\n### 7.2 依赖要求\n\n框架使用 Pydantic 作为数据验证层，示例代码中使用了 Cohere 作为 LLM 提供商。项目依赖包括：\n\n| 依赖包 | 用途 |\n|--------|------|\n| pydantic | 数据验证和序列化 |\n| cohere | LLM 接口调用 |\n| dotenv | 环境变量管理 |\n\n资料来源：[examples/hello_world/hello_world.py:1-8]()\n\n## 8 高级特性\n\n### 8.1 状态推理助手\n\n框架提供了 `_infer_state_helper()` 方法，用于辅助 LLM 在多个可能的状态之间进行选择：\n\n```python\ndef _infer_state_helper(self, *args: str) -> str:\n    prompt = I(\n        f\"\"\"\n        {self.initial_prompt}\n        Here are your past actions {self.memory.prompt()}.\n        Here are the next states you can go to: {\", \".join(args)}\n        Give the state that you want to go to. \n        1. Give one word and nothing else.\n        2. Be creative and try different routes.\n        \"\"\"\n    )\n    text = self.co.chat(temperature=1, message=prompt).text\n    return text\n```\n\n该方法通过精心设计的提示词模板，引导 LLM 选择下一个合适的状态，同时记录历史行为以保持上下文连贯性。\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:35-50]()\n\n### 8.2 类型别名定义\n\n框架大量使用 Python 的类型别名（Type Alias）来定义可达状态集合：\n\n```python\ntype BrowsingVideoReachable = Union[BrowsingVideo, ReadingComments]\ntype ReadingCommentsReachable = Union[BrowsingVideo, ReadingComments, PostComment]\n```\n\n这种设计使得状态转换的类型提示更加清晰，也便于静态分析和代码维护。\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:51-52]()\n\n## 9 应用场景\n\n### 9.1 B站冲浪者示例\n\n一个完整的示例展示了如何使用框架创建一个自动浏览 B 站视频、阅读评论和发表评论的 Agent：\n\n```mermaid\ngraph TD\n    A[BrowsingVideo] -->|搜索视频| B[选择视频]\n    B --> C[ReadingComments]\n    C -->|查看评论| D[选择评论]\n    D --> E[PostComment]\n    E -->|发表评论| A\n    D -->|继续浏览| A\n    C -->|继续浏览| A\n```\n\n该示例实现了四个状态：\n- **BrowsingVideo**：搜索和选择要观看的视频\n- **ReadingComments**：阅读视频的热门评论\n- **PostComment**：回复选定的评论\n- 各状态之间通过 `_infer_state_helper()` 方法进行智能转换\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:55-155]()\n\n## 10 设计优势\n\n| 优势 | 说明 |\n|------|------|\n| 简洁直观 | 状态即普通的 Python 类，易于理解和实现 |\n| 类型安全 | 基于 Pydantic 的数据验证和泛型支持 |\n| 可扩展性 | 可自由定义状态数量和转换逻辑 |\n| 线程安全 | 执行器使用锁保护共享状态 |\n| 循环执行 | 支持无限循环的任务执行 |\n| 记忆能力 | 内置 FIFO 队列支持历史记录管理 |\n\nCyclicAgent 通过有限状态机模式为 LLM Agent 的构建提供了一种结构清晰、易于维护的解决方案，使开发者能够专注于业务逻辑的实现，而无需担心底层的状态管理和执行调度。\n\n---\n\n<a id='page-2'></a>\n\n## 安装与依赖\n\n### 相关页面\n\n相关主题：[项目介绍](#page-1), [快速入门指南](#page-3)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [pyproject.toml](https://github.com/xingjianll/cyclic-agent/blob/main/pyproject.toml)\n- [README.md](https://github.com/xingjianll/cyclic-agent/blob/main/README.md)\n- [cyclic_agent/__init__.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/__init__.py)\n- [cyclic_agent/state.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/state.py)\n- [cyclic_agent/executor.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n</details>\n\n# 安装与依赖\n\n## 概述\n\nCyclicAgent 是一个基于有限状态机（FSM）设计的 LLM 驱动自主代理框架。该框架采用状态设计模式，将每个代理抽象为一个状态机，通过状态之间的转换实现循环执行。资料来源：[README.md:1-5]()\n\n安装与依赖模块定义了项目的基础运行环境、核心依赖包以及可选依赖项，是用户成功部署和使用该框架的前提条件。\n\n## 环境要求\n\n### Python 版本\n\n| 要求项 | 最低版本 | 说明 |\n|--------|----------|------|\n| Python | 3.11+ | 需要支持泛型类型参数语法 `class State[SigT]` |\n\n### 核心依赖\n\nCyclicAgent 的核心功能依赖于以下 Python 包：\n\n| 依赖包 | 版本要求 | 用途 |\n|--------|----------|------|\n| pydantic | ≥2.0 | 状态基类的数据模型实现 |\n| typing_extensions | 最新版 | 支持 Python 3.11 之前的类型注解 |\n\n核心包仅包含最基础的依赖，确保框架轻量化运行。资料来源：[cyclic_agent/state.py:1-6]()\n\n## 安装方式\n\n### 使用 pip 安装\n\nCyclicAgent 可通过 Python 包管理器 pip 直接安装：\n\n```shell\npip install cyclic-agent\n```\n\n该命令会自动安装所有核心依赖。资料来源：[README.md:8-10]()\n\n### 从源码安装\n\n对于开发者或需要修改源码的用户，可通过 GitHub 仓库克隆并安装：\n\n```shell\ngit clone https://github.com/xingjianll/cyclic-agent.git\ncd cyclic-agent\npip install -e .\n```\n\n## 核心模块依赖\n\n### 模块架构\n\n```mermaid\ngraph TD\n    A[cyclic_agent] --> B[state.py]\n    A --> C[executor.py]\n    A --> D[__init__.py]\n    \n    B --> E[pydantic.BaseModel]\n    C --> F[threading]\n    C --> G[time]\n    \n    style A fill:#e1f5fe\n    style B fill:#f3e5f5\n    style C fill:#fff3e0\n```\n\n### 状态基类依赖\n\n`State` 是框架的核心抽象类，继承自 `pydantic.BaseModel`，提供了状态机的数据验证和序列化能力。资料来源：[cyclic_agent/state.py:5]()\n\n```python\nfrom pydantic import BaseModel\n\nclass State[SigT](BaseModel):\n    @abstractmethod\n    def next(self, signal: SigT | None = None) -> State[SigT]:\n        \"\"\"转换到下一个状态\"\"\"\n        raise NotImplementedError\n```\n\n### 执行器依赖\n\n`CyclicExecutor` 负责管理状态机的生命周期，使用标准库的线程机制实现后台运行。资料来源：[cyclic_agent/executor.py:1-7]()\n\n| 模块 | 来源 | 用途 |\n|------|------|------|\n| threading | 标准库 | 多线程状态循环执行 |\n| time | 标准库 | 执行间隔控制 |\n\n## 可选依赖\n\n根据具体应用场景，用户可能需要安装以下可选依赖：\n\n### LLM 提供商\n\n| 包名 | 说明 | 用途示例 |\n|------|------|----------|\n| cohere | Cohere API 客户端 | 实现与 Cohere LLM 的交互 |\n\n安装可选 LLM 依赖：\n\n```shell\npip install cohere\n```\n\n### 环境变量管理\n\n| 包名 | 说明 |\n|------|------|\n| python-dotenv | 从 `.env` 文件加载环境变量 |\n\n### 第三方集成\n\n复杂示例（如 Bilibili 冲浪者）可能需要额外依赖：\n\n| 包名 | 用途 |\n|------|------|\n| bilibili-api-python | Bilibili API 封装 |\n| overrides | 方法重写装饰器 |\n\n## 环境变量配置\n\n### 必需的环境变量\n\n在使用 LLM 提供商时，需要配置相应的 API 密钥：\n\n```python\nimport os\nfrom dotenv import load_dotenv\n\nload_dotenv()  # 从 .env 文件加载环境变量\n\nco = cohere.Client(os.environ.get(\"COHERE_API_KEY\"))\n```\n\n### .env 文件示例\n\n```\nCOHERE_API_KEY=your_api_key_here\n```\n\n资料来源：[examples/hello_world/hello_world.py:1-11]()\n\n## 包导出结构\n\n框架通过 `__init__.py` 向外暴露核心接口：资料来源：[cyclic_agent/__init__.py:1-5]()\n\n```mermaid\ngraph LR\n    A[cyclic_agent] --> B[State]\n    A --> C[CyclicExecutor]\n    \n    B --> D[状态基类]\n    C --> E[执行器]\n```\n\n| 导出项 | 模块路径 | 说明 |\n|--------|----------|------|\n| `State` | cyclic_agent.state | 状态机抽象基类 |\n| `CyclicExecutor` | cyclic_agent.executor | 状态循环执行器 |\n\n## 安装验证\n\n安装完成后，可通过以下方式验证：\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\n\n# 验证导入成功\nprint(\"CyclicAgent 安装成功\")\n```\n\n## 依赖冲突处理\n\n### 类型注解兼容\n\n框架使用 Python 3.11+ 的新语法 `class State[SigT]`，如果使用旧版本 Python 可能需要以下导入：\n\n```python\nfrom __future__ import annotations\n```\n\n此导入使类型注解使用字符串延迟求值，确保与旧版本兼容。资料来源：[examples/hello_world/hello_world.py:1]()\n\n### Pydantic 版本\n\n框架使用 Pydantic v2 的配置方式：\n\n```python\nfrom pydantic import ConfigDict\n\nclass BilibiliStateBase(State[None]):\n    model_config = ConfigDict(arbitrary_types_allowed=True)\n```\n\n如使用 Pydantic v1，需要调整配置方式。\n\n## 快速开始依赖清单\n\n完整的快速开始示例所需依赖：\n\n| 依赖包 | 安装命令 | 用途 |\n|--------|----------|------|\n| cyclic-agent | `pip install cyclic-agent` | 核心框架 |\n| cohere | `pip install cohere` | LLM 调用 |\n| python-dotenv | `pip install python-dotenv` | 环境变量 |\n\n## 常见问题\n\n### Q: 是否需要安装可选依赖？\n\nA: 核心功能仅需安装 `cyclic-agent` 即可运行。可选依赖根据具体使用场景决定是否安装。\n\n### Q: 如何确认安装成功？\n\nA: 执行 `python -c \"from cyclic_agent import State, CyclicExecutor\"` 无报错即表示安装成功。\n\n### Q: 框架支持哪些 Python 版本？\n\nA: 推荐使用 Python 3.11+，以获得完整的类型注解支持。\n\n---\n\n<a id='page-3'></a>\n\n## 快速入门指南\n\n### 相关页面\n\n相关主题：[安装与依赖](#page-2), [State基类设计](#page-4), [Bilibili Surfer示例](#page-10)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [examples/hello_world/hello_world.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/hello_world/hello_world.py)\n- [cyclic_agent/executor.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n- [cyclic_agent/state.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/state.py)\n- [cyclic_agent/cot.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/cot.py)\n- [cyclic_agent/search.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/search.py)\n- [examples/bilibili_surfer/bilibili_surfer.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n- [examples/bilibili_surfer/fifo.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n</details>\n\n# 快速入门指南\n\n## 概述\n\nCyclicAgent 是一个基于有限状态机（FSM）设计的 LLM 驱动自主 AI Agent 框架。该框架采用状态设计模式，将每个 Agent 抽象为有限状态机，通过状态之间的转换实现 Agent 的循环执行能力。资料来源：[README.md:1-5]()\n\n## 核心概念\n\n### 状态（State）\n\n状态是 CyclicAgent 框架的基础单元。每个状态都继承自 `State` 基类，并实现 `next()` 方法来决定状态转换逻辑。资料来源：[cyclic_agent/state.py:7-10]()\n\n```python\nclass State[SigT](BaseModel):\n    @abstractmethod\n    def next(self, signal: SigT | None = None) -> State[SigT]:\n        \"\"\"Transition to the next state.\"\"\"\n        raise NotImplementedError\n```\n\n### 循环执行器（CyclicExecutor）\n\n`CyclicExecutor` 负责管理状态机的执行循环，通过独立的线程持续调用状态的 `next()` 方法来实现状态转换。资料来源：[cyclic_agent/executor.py:8-11]()\n\n```python\nclass CyclicExecutor:\n    def __init__(self, default_time_interval: float):\n        self.running = False\n        self.lock = threading.Lock()\n        self.default_time_interval = default_time_interval\n```\n\n## 工作原理\n\nCyclicAgent 的核心工作原理是将 Agent 抽象为有限状态机。在每个状态下，Agent 根据内部状态属性（如 memory、meta prompts）以及外部信号推断下一个状态，并与外部环境进行交互。所有状态都实现状态转换函数，返回另一个状态，从而实现状态的无限链接，使 Agent 具备\"循环\"特性。资料来源：[README.md:10-15]()\n\n```mermaid\ngraph TD\n    A[初始状态] --> B{State.next}\n    B -->|返回新状态| C[下一状态]\n    C --> B\n    B -->|接收外部信号| D[信号处理]\n    D --> C\n```\n\n## 安装与配置\n\n### 环境要求\n\n| 要求项 | 说明 |\n|--------|------|\n| Python 版本 | 3.8+ |\n| 核心依赖 | Pydantic |\n| LLM 提供商 | Cohere（示例使用） |\n| 环境管理 | dotenv |\n\n### 安装方式\n\n```shell\npip install cyclic-agent\n```\n\n### 环境变量配置\n\n创建 `.env` 文件并配置必要的 API 密钥：\n\n```bash\nCOHERE_API_KEY=your_cohere_api_key\n```\n\n## 快速开始\n\n### 环境准备\n\n1. 安装 cyclic-agent 包\n2. 配置环境变量或使用 `load_dotenv()` 加载 `.env` 文件\n3. 导入必要的模块：\n\n```python\nfrom __future__ import annotations\nfrom cyclic_agent import State, CyclicExecutor\n```\n\n### 基础示例：问答循环\n\n以下示例创建了一个简单的问答 Agent，包含两个相互转换的状态。资料来源：[examples/hello_world/hello_world.py:1-40]()\n\n```python\nfrom __future__ import annotations\nimport os\nimport time\n\nimport cohere\nfrom dotenv import load_dotenv\n\nfrom cyclic_agent import State, CyclicExecutor\n\nload_dotenv()\nco = cohere.Client(os.environ.get(\"COHERE_API_KEY\"))\n\n\nclass AskQuestion(State[None]):\n    def next(self, signal: None = None) -> AnswerQuestion:\n        response = co.chat(message=\"Ask a question\", temperature=1)\n        print(response.text)\n        return AnswerQuestion(question=response.text)\n\n\nclass AnswerQuestion(State[None]):\n    question: str\n\n    def next(self, signal: None = None) -> AskQuestion:\n        answer = co.chat(message=self.question)\n        print(answer)\n        return AskQuestion()\n\n\nif __name__ == \"__main__\":\n    initial_state = AskQuestion()\n    executor = CyclicExecutor(5)\n    executor.start(initial_state)\n    time.sleep(20)\n```\n\n### 状态转换流程\n\n```mermaid\ngraph LR\n    A[AskQuestion] -->|next()| B[AnswerQuestion]\n    B -->|next()| A\n    style A fill:#e1f5fe\n    style B fill:#fff3e0\n```\n\n## 进阶示例：B站冲浪 Agent\n\n以下示例展示了更复杂的状态机实现，包含浏览视频、阅读评论、发表评论等多个状态。资料来源：[examples/bilibili_surfer/bilibili_surfer.py:1-180]()\n\n### 状态结构\n\n| 状态类 | 功能 | 可转换状态 |\n|--------|------|------------|\n| `BrowsingVideo` | 搜索和浏览视频 | `BrowsingVideo`, `ReadingComments` |\n| `ReadingComments` | 读取视频评论 | `BrowsingVideo`, `ReadingComments`, `PostComment` |\n| `PostComment` | 发表/回复评论 | `BrowsingVideo` |\n\n### 状态基类设计\n\n所有 Bilibili 相关状态继承自 `BilibiliStateBase`，该基类封装了通用逻辑。资料来源：[examples/bilibili_surfer/bilibili_surfer.py:27-52]()\n\n```python\nclass BilibiliStateBase(State[None], ABC):\n    model_config = ConfigDict(arbitrary_types_allowed=True)\n    initial_prompt: str\n    memory: Fifo\n    co: Client\n    credential: Credential\n\n    def _infer_state_helper(self, *args: str) -> str:\n        prompt = I(\n            f\"\"\"\n            {self.initial_prompt}\n            Here are your past actions {self.memory.prompt()}.\n            Here are the next states you can go to: {\", \".join(args)}\n            Give the state that you want to go to. \n            1. Give one word and nothing else.\n            2. Be creative and try different routes.\n            \"\"\"\n        )\n        text = self.co.chat(temperature=1, message=prompt).text\n        return text\n```\n\n### 内存管理\n\n使用 FIFO 队列记录 Agent 的历史行为，辅助 LLM 做决策。资料来源：[examples/bilibili_surfer/fifo.py:1-30]()\n\n```python\nclass Fifo:\n    def __init__(self):\n        self.capacity = 100\n        self.queue = []\n        self.log_file = \"fifo_log.txt\"\n\n    def add(self, item):\n        if len(self.queue) >= self.capacity:\n            self.queue.pop(0)\n        timestamp = datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n        self.queue.append((item, timestamp))\n        self.log_to_file(item, timestamp)\n\n    def prompt(self):\n        return \"\\n\".join([f\"{time} - {text}\" for text, time in reversed(self.queue)])\n```\n\n### 完整状态转换图\n\n```mermaid\ngraph TD\n    A[BrowsingVideo] -->|搜索视频| B{状态选择}\n    B -->|BrowsingVideo| A\n    B -->|ReadingComments| C[ReadingComments]\n    C -->|读取评论| D{状态选择}\n    D -->|BrowsingVideo| A\n    D -->|ReadingComments| C\n    D -->|PostComment| E[PostComment]\n    E -->|发表评论| A\n    style A fill:#e1f5fe\n    style C fill:#e8f5e9\n    style E fill:#fff3e0\n```\n\n## 状态机类型定义\n\n框架使用 Python 类型别名定义状态转换规则。资料来源：[examples/bilibili_surfer/bilibili_surfer.py:54-55]()\n\n```python\ntype BrowsingVideoReachable = Union[BrowsingVideo, ReadingComments]\ntype ReadingCommentsReachable = Union[BrowsingVideo, ReadingComments, PostComment]\ntype PostCommentReachable = Union[BrowsingVideo]\n```\n\n## 执行器控制\n\n`CyclicExecutor` 提供以下控制方法：\n\n| 方法 | 功能 | 线程安全 |\n|------|------|----------|\n| `start(initial_state)` | 启动状态机 | 是 |\n| `pause()` | 暂停执行 | 是 |\n| `resume()` | 恢复执行 | 是 |\n| `kill()` | 停止并清理 | 是 |\n\n资料来源：[cyclic_agent/executor.py:13-31]()\n\n## 内置组件\n\n### 思维链（CoT）\n\n`CoT` 组件支持思维链推理模式。资料来源：[cyclic_agent/cot.py:1-20]()\n\n```python\nclass CoT(State[None]):\n    exit_: Callable[[str], State]\n    llm: State\n    prompt: str\n\n    def next(self, signal: None = None) -> State:\n        prompt = self.prompt + \"Let's think step by step.\"\n        def callback(answer: str) -> State:\n            return self.exit_(answer)\n        return self.llm(prompt=prompt, callback=callback)\n```\n\n### 搜索组件（Search）\n\n`Search` 组件提供搜索功能抽象。资料来源：[cyclic_agent/search.py:1-18]()\n\n```python\nclass Search(State[None]):\n    query: str\n    exit_: Callable[[[Annotated[str, \"search result\"]]], State]\n\n    def next(self, signal: None = None) -> State:\n        search_result = self.search(self.query)\n        return self.exit_(search_result)\n\n    def search(self, query: str) -> str:\n        raise NotImplementedError\n```\n\n## 最佳实践\n\n### 前向引用注意事项\n\n由于状态类之间存在循环引用，必须使用 `from __future__ import annotations` 启用前向引用支持。资料来源：[examples/hello_world/hello_world.py:3]()\n\n```python\nfrom __future__ import annotations\n```\n\n### 模型_dump() 的使用\n\n在状态转换时使用 Pydantic 的 `model_dump()` 方法传递状态数据。资料来源：[examples/bilibili_surfer/bilibili_surfer.py:71-73]()\n\n```python\nreturn BrowsingVideo(**self.model_dump(exclude={'video_bvid', 'video_title', 'video_description'}))\n```\n\n### 异步操作处理\n\n使用 `asyncio.run()` 在同步状态方法中处理异步 API 调用。资料来源：[examples/bilibili_surfer/bilibili_surfer.py:87-90]()\n\n```python\nresponse = asyncio.run(comment.send_comment(\n    text=f\"{response} {footnote}\",\n    oid=video.Video(bvid=self.video_bvid).get_aid(),\n    type_=CommentResourceType.VIDEO,\n    credential=self.credential\n))\n```\n\n### LLM 决策引导\n\n通过结构化的 prompt 引导 LLM 做出符合预期的状态选择决策。资料来源：[examples/bilibili_surfer/bilibili_surfer.py:35-48]()\n\n```python\nprompt = I(\n    f\"\"\"\n    {self.initial_prompt}\n    Here are your past actions {self.memory.prompt()}.\n    Here are the next states you can go to: {\", \".join(args)}\n    Give the state that you want to go to. \n    1. Give one word and nothing else.\n    2. Be creative and try different routes.\n    \"\"\"\n)\n```\n\n## 下一步\n\n- 深入阅读 [核心组件文档](./core-components.md) 了解更多内置组件\n- 查看 [示例项目](./examples.md) 获取更多实践参考\n- 探索 [高级用法](./advanced-usage.md) 学习自定义状态转换逻辑\n\n---\n\n<a id='page-4'></a>\n\n## State基类设计\n\n### 相关页面\n\n相关主题：[CyclicExecutor执行器](#page-5), [有限状态机模式](#page-6)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [cyclic_agent/state.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/state.py)\n- [cyclic_agent/executor.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n- [cyclic_agent/__init__.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/__init__.py)\n- [cyclic_agent/search.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/search.py)\n- [cyclic_agent/cot.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/cot.py)\n- [examples/hello_world/hello_world.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/hello_world/hello_world.py)\n- [examples/bilibili_surfer/bilibili_surfer.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n</details>\n\n# State基类设计\n\n## 概述\n\nCyclicAgent框架的核心设计基于**有限状态机（FSM）**概念，通过状态设计模式将AI Agent抽象为可循环执行的状态机。`State`基类是整个框架的基础抽象，定义了状态转换的标准接口。\n\n状态机的工作原理是：每个状态实现一个`next()`方法，该方法根据内部状态属性（如memory、meta prompts等）和外部信号推断下一个状态，并返回另一个状态对象。这种设计使得状态转换操作可以无限链式执行，从而实现Agent的\"循环\"特性。\n\n## 核心架构\n\n### 状态转换流程\n\n```mermaid\ngraph TD\n    A[State开始] --> B{执行next方法}\n    B --> C[根据业务逻辑确定下一状态]\n    C --> D[返回新状态对象]\n    D --> E{CyclicExecutor是否继续?}\n    E -->|是| B\n    E -->|否| F[结束]\n    \n    G[外部信号] -.-> B\n    H[内部状态属性] -.-> B\n```\n\n### 状态与执行器的关系\n\n```mermaid\ngraph LR\n    A[CyclicExecutor] -->|持有当前状态| B[State实例]\n    B -->|调用next返回| C[下一State]\n    C -->|循环| B\n    D[Thread] -->|运行主循环| A\n```\n\n## State基类规范\n\n### 基类定义\n\n```python\nclass State[SigT](BaseModel):\n    @abstractmethod\n    def next(self, signal: SigT | None = None) -> State[SigT]:\n        \"\"\"Transition to the next state.\"\"\"\n        raise NotImplementedError\n```\n\n资料来源：[cyclic_agent/state.py:6-10]()\n\n### 关键特性\n\n| 特性 | 说明 |\n|------|------|\n| 泛型设计 | 使用Python泛型`[SigT]`定义信号类型参数 |\n| Pydantic集成 | 继承`BaseModel`，支持数据验证和序列化 |\n| 抽象方法 | `next()`必须由子类实现 |\n| 信号机制 | 支持可选的外部信号参数 |\n\n### 类型参数说明\n\n| 参数 | 含义 | 用途 |\n|------|------|------|\n| `SigT` | Signal Type | 定义状态间传递的信号数据类型 |\n| `State[None]` | 无信号状态 | 状态间无需传递数据，如`AskQuestion` |\n| `State[str]` | 字符串信号 | 可携带文本信息进行状态转换 |\n\n## 执行器设计\n\n### CyclicExecutor类\n\n`CyclicExecutor`负责在独立线程中运行状态机的主循环，通过`time.sleep()`控制状态转换的时间间隔。\n\n```python\nclass CyclicExecutor:\n    def __init__(self, default_time_interval: float):\n        self.running = False\n        self.lock = threading.Lock()\n        self.default_time_interval = default_time_interval\n        self.killed = False\n        self.thread = None\n```\n\n资料来源：[cyclic_agent/executor.py:1-7]()\n\n### 执行器控制方法\n\n| 方法 | 功能 | 线程安全性 |\n|------|------|------------|\n| `start(initial_state)` | 启动执行线程 | 线程安全 |\n| `pause()` | 暂停状态机 | 线程安全 |\n| `resume()` | 恢复执行 | 线程安全 |\n| `kill()` | 终止执行 | 线程安全 |\n\n### 主循环实现\n\n```python\ndef _main_loop(self, state: State) -> None:\n    while True:\n        if self.killed:\n            return\n        if self.running:\n            state = state.next()\n            time.sleep(self.default_time_interval)\n```\n\n资料来源：[cyclic_agent/executor.py:30-36]()\n\n## 状态实现模式\n\n### 简单状态示例\n\n最简单的状态实现只需继承`State[None]`，当状态不需要传递数据时：\n\n```python\nclass AskQuestion(State[None]):\n    def next(self, signal: None = None) -> AnswerQuestion:\n        response = co.chat(message=\"Ask a question\", temperature=1)\n        return AnswerQuestion(question=response.text)\n```\n\n资料来源：[examples/hello_world/hello_world.py:14-18]()\n\n### 带状态属性的状态\n\n通过Pydantic的字段定义，状态可以持有任意业务数据：\n\n```python\nclass AnswerQuestion(State[None]):\n    question: str  # 状态属性：保存问题内容\n    \n    def next(self, signal: None = None) -> AskQuestion:\n        answer = co.chat(message=self.question)\n        return AskQuestion()\n```\n\n资料来源：[examples/hello_world/hello_world.py:20-25]()\n\n### 复杂状态基类\n\n实际应用中，状态通常需要共享资源。框架通过继承模式实现：\n\n```python\nclass BilibiliStateBase(State[None], ABC):\n    model_config = ConfigDict(arbitrary_types_allowed=True)\n    initial_prompt: str\n    memory: Fifo\n    co: Client\n    credential: Credential\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:27-32]()\n\n### 类型别名定义可到达状态\n\n```python\ntype BrowsingVideoReachable = Union[BrowsingVideo, ReadingComments]\n\nclass BrowsingVideo(BilibiliStateBase):\n    @overrides\n    def next(self, signal: None = None) -> BrowsingVideoReachable:\n        ...\n        match self._infer_state_helper('BrowsingVideo', 'ReadingComments'):\n            case 'BrowsingVideo':\n                return self\n            case 'ReadingComments':\n                return ReadingComments(...)\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:72-89]()\n\n## 状态转换模式\n\n### 一对一转换\n\n最基础的转换模式：每个状态明确返回下一个状态类型：\n\n```mermaid\ngraph LR\n    A[AskQuestion] -->|返回AnswerQuestion| B[AnswerQuestion]\n    B -->|返回AskQuestion| A\n```\n\n### 多分支转换\n\n通过类型联合和模式匹配实现条件转换：\n\n```python\ntype ReadingCommentsReachable = Union[BrowsingVideo, ReadingComments, PostComment]\n\ndef next(self, signal: None = None) -> ReadingCommentsReachable:\n    ...\n    match self._infer_state_helper('BrowsingVideo', 'ReadingComments', 'PostComment'):\n        case 'BrowsingVideo':\n            return BrowsingVideo(...)\n        case 'ReadingComments':\n            return self\n        case 'PostComment':\n            return PostComment(...)\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:116-129]()\n\n### 自引用转换\n\n状态可以返回自身保持不变：\n\n```python\ncase 'BrowsingVideo':\n    return self  # 保持当前状态\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:118]()\n\n## 内置状态组件\n\n### Search状态\n\n框架提供了可扩展的`Search`状态基类：\n\n```python\nclass Search(State[None]):\n    query: str\n    exit_: Callable[[[Annotated[str, \"search result\"]]], State]\n    \n    def next(self, signal: None = None) -> State:\n        search_result = self.search(self.query)\n        return self.exit_(search_result)\n    \n    def search(self, query: str) -> str:\n        raise NotImplementedError\n```\n\n资料来源：[cyclic_agent/search.py:1-12]()\n\n### Chain of Thought状态\n\n```python\nclass CoT(State[None]):\n    exit_: Callable[[str], State]\n    llm: State\n    prompt: str\n    \n    def next(self, signal: None = None) -> State:\n        prompt = self.prompt + \"Let's think step by step.\"\n        def callback(answer: str) -> State:\n            return self.exit_(answer)\n        return self.llm(prompt=prompt, callback=callback)\n```\n\n资料来源：[cyclic_agent/cot.py:1-16]()\n\n## 包导出结构\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\n\n__all__ = [\"State\", \"CyclicExecutor\"]\n```\n\n资料来源：[cyclic_agent/__init__.py:1-6]()\n\n## 使用流程\n\n```mermaid\ngraph TD\n    A[定义State子类] --> B[实现next方法]\n    B --> C[创建初始状态实例]\n    C --> D[创建CyclicExecutor]\n    D --> E[调用start方法]\n    E --> F[线程运行主循环]\n    F --> G[状态无限转换]\n    G --> H[外部调用kill终止]\n```\n\n## 设计优势\n\n| 优势 | 说明 |\n|------|------|\n| 简洁性 | 单一抽象方法`next()`定义状态行为 |\n| 灵活性 | Pydantic提供强大的数据验证 |\n| 可扩展性 | 继承基类即可创建新状态类型 |\n| 类型安全 | 泛型设计支持类型检查 |\n| 可测试性 | 每个状态独立，易于单元测试 |\n\n## 最佳实践\n\n### 1. 前向引用声明\n\n使用状态类型时需要前向引用：\n\n```python\nfrom __future__ import annotations\n\nclass AskQuestion(State[None]):\n    def next(self, signal: None = None) -> AnswerQuestion:\n        ...\n```\n\n资料来源：[examples/hello_world/hello_world.py:1-2]()\n\n### 2. 使用`@overrides`装饰器\n\n明确标注方法重写：\n\n```python\nfrom overrides import overrides\n\nclass BrowsingVideo(BilibiliStateBase):\n    @overrides\n    def next(self, signal: None = None) -> BrowsingVideoReachable:\n        ...\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:69-72]()\n\n### 3. 状态继承层次\n\n复杂应用建议使用多层继承：\n\n```mermaid\ngraph TD\n    A[State基类] --> B[业务状态基类]\n    B --> C[BrowsingVideo]\n    B --> D[ReadingComments]\n    B --> E[PostComment]\n```\n\n### 4. 内存管理\n\n使用`model_dump()`传递状态属性：\n\n```python\nreturn BrowsingVideo(**self.model_dump(exclude={'video_bvid', 'video_title', 'video_description'}))\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:83-85]()\n\n---\n\n<a id='page-5'></a>\n\n## CyclicExecutor执行器\n\n### 相关页面\n\n相关主题：[State基类设计](#page-4), [快速入门指南](#page-3)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [cyclic_agent/executor.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n- [cyclic_agent/state.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/state.py)\n- [cyclic_agent/__init__.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/__init__.py)\n- [examples/hello_world/hello_world.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/hello_world/hello_world.py)\n- [examples/bilibili_surfer/bilibili_surfer.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n- [examples/bilibili_surfer/fifo.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n</details>\n\n# CyclicExecutor执行器\n\n## 概述\n\nCyclicExecutor是CyclicAgent框架的核心执行引擎，负责驱动基于有限状态机（FSM）的自主代理运行。该执行器通过多线程机制和状态转换循环，使AI代理能够在各个状态之间持续流转，从而实现完全自主的AI行为。\n\nCyclicExecutor的设计遵循状态设计模式，将每个代理抽象为一个有限状态机，其中每个状态都包含一个`next()`方法，该方法根据内部状态属性（如内存、元提示等）以及外部信号推断下一个状态，并返回另一个状态对象。这种设计使得状态转换操作可以无限链接，从而形成\"循环\"的代理行为。\n\n资料来源：[cyclic_agent/executor.py:1-44](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n\n## 核心架构\n\n### 组件关系\n\nCyclicExecutor与State基类之间的关系构成了框架的核心架构。State类作为所有状态节点的抽象基类，定义了状态转换的接口规范；CyclicExecutor则负责按照设定的节奏驱动状态机持续运行。\n\n```mermaid\ngraph TD\n    A[CyclicExecutor] -->|管理| B[State 状态节点]\n    B -->|返回| B\n    A -->|启动线程| C[_main_loop 主循环]\n    C -->|循环调用| D[state.next]\n    D -->|状态转换| B\n```\n\n### 类结构\n\n| 类名 | 文件位置 | 职责 |\n|------|----------|------|\n| CyclicExecutor | cyclic_agent/executor.py | 状态机执行引擎 |\n| State | cyclic_agent/state.py | 状态抽象基类 |\n| Timer | cyclic_agent/executor.py | 占位类（未实现） |\n\n资料来源：[cyclic_agent/executor.py:1-44](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)，[cyclic_agent/state.py:1-20](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/state.py)\n\n## CyclicExecutor类详解\n\n### 类定义与初始化\n\n```python\nclass CyclicExecutor:\n    def __init__(self, default_time_interval: float):\n        self.running = False\n        self.lock = threading.Lock()\n        self.default_time_interval = default_time_interval\n        self.killed = False\n        self.thread = None\n```\n\nCyclicExecutor在初始化时接受一个`default_time_interval`参数，该参数指定状态转换之间的默认时间间隔（秒）。初始化后，执行器处于停止状态，需要通过`start()`方法启动。\n\n资料来源：[cyclic_agent/executor.py:8-14](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n\n### 生命周期控制方法\n\nCyclicExecutor提供了完整的生命周期控制接口，支持启动、暂停、恢复和终止操作：\n\n| 方法 | 功能 | 线程安全 |\n|------|------|----------|\n| start(initial_state) | 启动执行器，创建新线程运行主循环 | 否（仅首次调用有效） |\n| pause() | 暂停状态机执行 | 是（使用Lock） |\n| resume() | 恢复状态机执行 | 是（使用Lock） |\n| kill() | 彻底终止执行器 | 是（使用Lock） |\n\n```python\ndef start(self, initial_state: State) -> None:\n    if not self.running:\n        self.running = True\n        self.thread = threading.Thread(target=self._main_loop, args=(initial_state,))\n        self.thread.start()\n```\n\n`start()`方法检查执行器是否已在运行，若否则创建新的后台线程并启动主循环。初始状态作为参数传入，该状态将成为状态机的第一个活跃节点。\n\n```python\ndef kill(self):\n    with self.lock:\n        self.killed = True\n        self.running = False\n    if self.thread:\n        self.thread.join()\n```\n\n`kill()`方法通过设置`killed`标志并调用线程的`join()`方法确保线程完全终止，实现执行器的优雅关闭。\n\n资料来源：[cyclic_agent/executor.py:16-39](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n\n### 主循环机制\n\n主循环是CyclicExecutor的核心，它在独立线程中持续运行，不断调用当前状态的`next()`方法并接收返回的下一个状态：\n\n```python\ndef _main_loop(self, state: State) -> None:\n    while True:\n        if self.killed:\n            return\n\n        if self.running:\n            state = state.next()\n            time.sleep(self.default_time_interval)\n```\n\n主循环的工作流程如下：首先检查`killed`标志，若为真则直接返回退出循环；然后检查`running`标志，在执行器处于运行状态时，调用当前状态的`next()`方法获取下一个状态对象，并用返回值更新当前状态引用；最后按照`default_time_interval`设定的时间间隔休眠。\n\n```mermaid\ngraph TD\n    A[开始循环] --> B{killed == True?}\n    B -->|是| Z[退出循环]\n    B -->|否| C{running == True?}\n    C -->|否| A\n    C -->|是| D[调用 state.next]\n    D --> E[获取下一状态]\n    E --> F[更新 state 引用]\n    F --> G[休眠 default_time_interval]\n    G --> A\n```\n\n资料来源：[cyclic_agent/executor.py:41-48](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n\n## State基类\n\nState是所有状态节点的抽象基类，基于Pydantic的BaseModel实现，支持类型提示和自动验证：\n\n```python\nclass State[SigT](BaseModel):\n    @abstractmethod\n    def next(self, signal: SigT | None = None) -> State[SigT]:\n        \"\"\"Transition to the next state.\"\"\"\n        raise NotImplementedError\n```\n\nState类使用Python 3.12引入的泛型参数`SigT`来指定信号的泛型类型。`next()`方法是抽象方法，要求所有子类必须实现，用于定义状态转换逻辑并返回下一个状态对象。\n\n状态转换的核心约定是：每个状态的`next()`方法返回另一个State对象，这个返回的状态将成为下一个循环迭代的当前状态。这种设计使得状态转换形成了一个可以无限持续的循环。\n\n资料来源：[cyclic_agent/state.py:1-20](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/state.py)\n\n## 使用模式与示例\n\n### 基础问答模式\n\n最简单的应用场景是两个状态之间来回切换，实现自动问答功能：\n\n```python\nclass AskQuestion(State[None]):\n    def next(self, signal: None = None) -> AnswerQuestion:\n        response = co.chat(message=\"Ask a question\", temperature=1)\n        print(response.text)\n        return AnswerQuestion(question=response.text)\n\nclass AnswerQuestion(State[None]):\n    question: str\n\n    def next(self, signal: None = None) -> AskQuestion:\n        answer = co.chat(message=self.question)\n        print(answer)\n        return AskQuestion()\n\nif __name__ == \"__main__\":\n    initial_state = AskQuestion()\n    executor = CyclicExecutor(5)\n    executor.start(initial_state)\n```\n\n该示例创建了两个状态：AskQuestion向大模型提问，AnswerQuestion接收问题并回答。两个状态相互返回对方，形成无限循环的执行流。执行器设置5秒间隔，控制状态转换的频率。\n\n资料来源：[examples/hello_world/hello_world.py:1-38](https://github.com/xingjianll/cyclic-agent/blob/main/examples/hello_world/hello_world.py)\n\n### 复杂多状态模式\n\nBilibili冲浪者示例展示了更复杂的应用，包含浏览视频、阅读评论和发表评论三个主要状态：\n\n```python\nclass BrowsingVideo(BilibiliStateBase):\n    @overrides\n    def next(self, signal: None = None) -> BrowsingVideoReachable:\n        # 搜索视频、选择视频\n        # 根据LLM决策返回下一状态\n        match self._infer_state_helper('BrowsingVideo', 'ReadingComments'):\n            case 'BrowsingVideo':\n                return self\n            case 'ReadingComments':\n                return ReadingComments(**self.model_dump(), ...)\n\nclass ReadingComments(BilibiliStateBase):\n    @overrides\n    def next(self, signal: None = None) -> ReadingCommentsReachable:\n        # 获取评论、选择评论\n        match self._infer_state_helper('BrowsingVideo', 'ReadingComments', 'PostComment'):\n            case 'BrowsingVideo':\n                return BrowsingVideo(...)\n            case 'ReadingComments':\n                return self\n            case 'PostComment':\n                return PostComment(...)\n\nclass PostComment(BilibiliStateBase):\n    @overrides\n    def next(self, signal: None = None) -> PostCommentReachable:\n        # 发表评论、发布动态\n        return BrowsingVideo(...)\n```\n\n状态之间通过类型别名（Type Alias）定义可达关系，增强了类型安全性和代码可读性：\n\n```python\ntype BrowsingVideoReachable = Union[BrowsingVideo, ReadingComments]\ntype ReadingCommentsReachable = Union[BrowsingVideo, ReadingComments, PostComment]\ntype PostCommentReachable = Union[BrowsingVideo]\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:1-180](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n\n### 状态转换流程图\n\n```mermaid\ngraph LR\n    A[BrowsingVideo<br/>浏览视频] -->|阅读评论| B[ReadingComments<br/>阅读评论]\n    B -->|继续浏览| A\n    B -->|发表评论| C[PostComment<br/>发表评论]\n    C -->|完成| A\n    A -->|继续浏览| A\n```\n\n### 内存与记忆机制\n\n复杂代理通常需要维护内存以追踪历史行为。示例中的Fifo类实现了先入先出队列：\n\n```python\nclass Fifo:\n    def __init__(self):\n        self.capacity = 100\n        self.queue = []\n        self.log_file = \"fifo_log.txt\"\n\n    def add(self, item):\n        if len(self.queue) >= self.capacity:\n            self.queue.pop(0)\n        self.queue.append((item, datetime.now()))\n\n    def prompt(self):\n        return \"\\n\".join([f\"{time} - {text}\" for text, time in reversed(self.queue)])\n```\n\n状态在转换时将行为记录到内存中，LLM在决策时会参考这些历史记录来生成更智能的下一状态选择。\n\n资料来源：[examples/bilibili_surfer/fifo.py:1-30](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n\n## 线程安全机制\n\nCyclicExecutor使用`threading.Lock`保护共享状态，确保多线程环境下的安全访问：\n\n```python\nclass CyclicExecutor:\n    def __init__(self, default_time_interval: float):\n        self.running = False\n        self.lock = threading.Lock()\n        # ...\n\n    def pause(self):\n        with self.lock:\n            self.running = False\n\n    def resume(self):\n        with self.lock:\n            self.running = True\n```\n\n`with self.lock`语句确保在修改`running`标志时获得锁，防止竞态条件。由于Python的GIL特性，这种粗粒度的锁策略在大多数场景下已经足够安全。\n\n资料来源：[cyclic_agent/executor.py:8-34](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n\n## 模块导出\n\ncyclic_agent包的公共接口通过`__init__.py`导出：\n\n```python\nfrom cyclic_agent.state import State\nfrom cyclic_agent.executor import CyclicExecutor\n\n__all__ = [\"State\", \"CyclicExecutor\"]\n```\n\n使用者只需导入这两个核心组件即可开始构建自主代理应用。\n\n资料来源：[cyclic_agent/__init__.py:1-6](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/__init__.py)\n\n## 最佳实践\n\n### 初始化配置\n\n| 配置项 | 说明 | 推荐值 |\n|--------|------|--------|\n| default_time_interval | 状态转换间隔（秒） | 3-10秒 |\n| 初始状态选择 | 应选择有明确转换路径的状态 | 确保能进入循环 |\n\n### 状态设计原则\n\n1. **单一职责**：每个状态应专注于特定功能领域\n2. **幂等性**：状态的`next()`方法应能安全重复调用\n3. **状态保持**：使用Pydantic的`model_dump()`传递上下文数据\n4. **类型约束**：通过Type Alias明确状态的可达转换\n\n### 资源管理\n\n- 长时间运行的应用应设置外部超时机制\n- 使用`kill()`方法确保程序能正常退出\n- 配合外部信号（如SIGTERM）实现优雅关闭\n\n---\n\n<a id='page-6'></a>\n\n## 有限状态机模式\n\n### 相关页面\n\n相关主题：[State基类设计](#page-4), [CyclicExecutor执行器](#page-5)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [cyclic_agent/state.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/state.py)\n- [cyclic_agent/executor.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n- [examples/bilibili_surfer/bilibili_surfer.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n- [examples/hello_world/hello_world.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/hello_world/hello_world.py)\n- [cyclic_agent/__init__.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/__init__.py)\n- [examples/bilibili_surfer/fifo.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n</details>\n\n# 有限状态机模式\n\n## 概述\n\nCyclicAgent 框架的核心设计理念是将智能代理（Agent）抽象为**有限状态机（Finite State Machine, FSM）**。这一设计采用了状态模式（State Design Pattern），使代理能够根据内部状态属性（如记忆、元提示等）以及外部信号，在不同状态之间进行推断和转换。\n\n在 CyclicAgent 中，所有状态都实现了状态转换函数，该函数返回另一个状态。这种设计允许状态转换操作无限进行，从而使代理形成\"循环\"执行模式。资料来源：[README.md]()\n\n## 核心组件\n\n### State 基类\n\n`State` 是整个框架的抽象基类，定义在 `cyclic_agent/state.py` 中。它使用了 Python 的泛型语法来表示状态可接收的信号类型。\n\n```python\nclass State[SigT](BaseModel):\n    @abstractmethod\n    def next(self, signal: SigT | None = None) -> State[SigT]:\n        \"\"\"Transition to the next state.\"\"\"\n        raise NotImplementedError\n```\n\n| 属性/方法 | 类型 | 说明 |\n|-----------|------|------|\n| `SigT` | 泛型类型参数 | 表示状态可接收的信号类型 |\n| `next(signal)` | 抽象方法 | 执行状态转换，返回下一个状态 |\n| `model_dump()` | 继承自 BaseModel | 序列化状态对象为字典 |\n\nState 类继承自 Pydantic 的 `BaseModel`，这意味着所有具体状态都自动具备以下能力：\n\n- 自动数据验证\n- JSON 序列化/反序列化\n- 类型提示支持\n\n资料来源：[cyclic_agent/state.py:8-13]()\n\n### CyclicExecutor 执行器\n\n`CyclicExecutor` 负责运行状态机，通过独立的线程持续执行状态转换循环。\n\n```python\nclass CyclicExecutor:\n    def __init__(self, default_time_interval: float):\n        self.running = False\n        self.lock = threading.Lock()\n        self.default_time_interval = default_time_interval\n        self.killed = False\n        self.thread = None\n```\n\n| 方法 | 说明 |\n|------|------|\n| `start(initial_state)` | 启动执行器，传入初始状态 |\n| `pause()` | 暂停状态机执行 |\n| `resume()` | 恢复状态机执行 |\n| `kill()` | 终止执行器 |\n| `_main_loop()` | 内部主循环，持续调用 `state.next()` |\n\n执行器使用线程安全的方式管理状态转换：\n\n```python\ndef _main_loop(self, state: State) -> None:\n    while True:\n        if self.killed:\n            return\n        if self.running:\n            state = state.next()\n            time.sleep(self.default_time_interval)\n```\n\n资料来源：[cyclic_agent/executor.py:1-36]()\n\n## 架构图\n\n```mermaid\ngraph TD\n    A[初始状态 StartState] -->|next()| B[状态 B]\n    B -->|next()| C[状态 C]\n    C -->|next()| D[...]\n    D -->|next()| E[状态 N]\n    E -->|next()| A\n    \n    F[CyclicExecutor] -->|管理| A\n    F -->|管理| B\n    F -->|管理| C\n    \n    G[Signal] -.->|可选输入| A\n    G -.->|可选输入| B\n    G -.->|可选输入| C\n    \n    H[Memory Context] -.->|状态上下文| A\n    H -.->|状态上下文| B\n```\n\n## 状态转换机制\n\n### 基础转换模式\n\n最简单的状态转换是两个状态之间的循环切换，如 hello_world 示例所示：\n\n```python\nclass AskQuestion(State[None]):\n    def next(self, signal: None = None) -> AnswerQuestion:\n        response = co.chat(message=\"Ask a question\", temperature=1)\n        return AnswerQuestion(question=response.text)\n\n\nclass AnswerQuestion(State[None]):\n    question: str\n\n    def next(self, signal: None = None) -> AskQuestion:\n        answer = co.chat(message=self.question)\n        return AskQuestion()\n```\n\n每个状态通过 `next()` 方法返回下一个状态，形成无限循环。资料来源：[examples/hello_world/hello_world.py:10-27]()\n\n### 类型联合定义可达状态\n\nCyclicAgent 使用 Python 的类型别名（Type Alias）和 `type` 声明来明确每个状态可以转换到哪些其他状态：\n\n```python\ntype BrowsingVideoReachable = Union[BrowsingVideo, ReadingComments]\n\nclass BrowsingVideo(BilibiliStateBase):\n    @overrides\n    def next(self, signal: None = None) -> BrowsingVideoReachable:\n        # ... 逻辑处理\n        match self._infer_state_helper('BrowsingVideo', 'ReadingComments'):\n            case 'BrowsingVideo':\n                return self\n            case 'ReadingComments':\n                return ReadingComments(**self.model_dump(), ...)\n```\n\n这种设计提供了：\n\n- **类型安全**：静态检查状态转换的合法性\n- **IDE 支持**：自动补全和导航\n- **文档化**：明确每个状态的转换路径\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:44-59]()\n\n### 使用 match-case 进行状态推断\n\n在实际应用中，状态转换往往需要根据 LLM 的响应来决定。CyclicAgent 使用 `match-case` 语法匹配 LLM 返回的状态名称：\n\n```python\nmatch self._infer_state_helper('BrowsingVideo', 'ReadingComments', 'PostComment'):\n    case 'BrowsingVideo':\n        return BrowsingVideo(**self.model_dump(exclude={...}))\n    case 'ReadingComments':\n        return self\n    case 'PostComment':\n        return PostComment(**self.model_dump(), reply_to=cmt['content']['message'], ...)\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:93-100]()\n\n## 状态上下文与记忆\n\n### BilibiliStateBase 基础状态类\n\n示例项目中的 `BilibiliStateBase` 展示了如何为状态添加共享上下文：\n\n```python\nclass BilibiliStateBase(State[None], ABC):\n    model_config = ConfigDict(arbitrary_types_allowed=True)\n    initial_prompt: str\n    memory: Fifo\n    co: Client\n    credential: Credential\n```\n\n| 上下文属性 | 类型 | 说明 |\n|-----------|------|------|\n| `initial_prompt` | str | 初始化 LLM 交互的提示词 |\n| `memory` | Fifo | FIFO 队列，记录历史行为 |\n| `co` | Client | Cohere LLM 客户端 |\n| `credential` | Credential | Bilibili API 认证凭证 |\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:28-35]()\n\n### FIFO 记忆组件\n\n`Fifo` 类实现了有限容量的先进先出队列，用于存储代理的历史行为：\n\n```python\nclass Fifo:\n    def __init__(self):\n        self.capacity = 100\n        self.queue = []\n        self.log_file = \"fifo_log.txt\"\n\n    def add(self, item):\n        if len(self.queue) >= self.capacity:\n            self.queue.pop(0)  # 移除最旧的记录\n        timestamp = datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n        self.queue.append((item, timestamp))\n        self.log_to_file(item, timestamp)\n\n    def prompt(self):\n        return \"\\n\".join([f\"{time} - {text}\" for text, time in reversed(self.queue)])\n```\n\n| 方法 | 说明 |\n|------|------|\n| `add(item)` | 添加新记录，自动管理容量上限 |\n| `prompt()` | 生成提示字符串，最新记录在前 |\n| `log_to_file()` | 将记录持久化到日志文件 |\n\n资料来源：[examples/bilibili_surfer/fifo.py:1-34]()\n\n## 完整工作流程图\n\n```mermaid\nsequenceDiagram\n    participant User as 用户\n    participant Executor as CyclicExecutor\n    participant State as 当前状态\n    participant LLM as LLM API\n    participant Memory as 记忆组件\n    participant Env as 外部环境\n\n    User->>Executor: start(initial_state)\n    loop 持续执行\n        Executor->>State: next(signal?)\n        State->>Memory: prompt() 获取历史\n        State->>State: 构建决策提示\n        State->>LLM: chat(prompt)\n        LLM-->>State: 返回决策结果\n        State->>State: match-case 匹配结果\n        State->>State: model_dump() 传递上下文\n        State->>Env: 执行动作（如发帖、评论）\n        State-->>Executor: 返回下一状态\n        Executor->>Executor: sleep(interval)\n    end\n```\n\n## 导出接口\n\nCyclicAgent 包仅导出两个核心类供用户使用：\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\n```\n\n| 导出项 | 来源文件 | 说明 |\n|-------|----------|------|\n| `State` | cyclic_agent/state.py | 状态机抽象基类 |\n| `CyclicExecutor` | cyclic_agent/executor.py | 状态机执行器 |\n\n资料来源：[cyclic_agent/__init__.py:1-6]()\n\n## 使用示例\n\n### 最小示例：问答循环\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\n\nclass AskQuestion(State[None]):\n    def next(self, signal=None) -> AnswerQuestion:\n        response = co.chat(message=\"Ask a question\")\n        return AnswerQuestion(question=response.text)\n\nclass AnswerQuestion(State[None]):\n    question: str\n    def next(self, signal=None) -> AskQuestion:\n        answer = co.chat(message=self.question)\n        return AskQuestion()\n\n# 启动执行器\nexecutor = CyclicExecutor(5)  # 每次转换间隔 5 秒\nexecutor.start(AskQuestion())\n```\n\n### Bilibili 冲浪代理\n\n完整的 Bilibili 冲浪代理展示了复杂的实际应用场景，包含四个状态：\n\n| 状态 | 可达状态 | 功能 |\n|------|----------|------|\n| `BrowsingVideo` | `BrowsingVideo`, `ReadingComments` | 搜索和浏览视频 |\n| `ReadingComments` | `BrowsingVideo`, `ReadingComments`, `PostComment` | 阅读视频评论 |\n| `PostComment` | `BrowsingVideo` | 回复评论 |\n| 初始状态 | `BrowsingVideo` | 从视频浏览开始 |\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:44-140]()\n\n## 设计优势\n\n| 优势 | 说明 |\n|------|------|\n| **状态内聚** | 每个状态包含自身数据和转换逻辑 |\n| **易于扩展** | 添加新状态只需继承 `State` 并实现 `next()` |\n| **类型安全** | 静态类型检查确保状态转换的合法性 |\n| **测试友好** | 每个状态可独立单元测试 |\n| **无限循环** | CyclicExecutor 支持状态机持续运行 |\n| **上下文传递** | 通过 Pydantic 的 `model_dump()` 传递状态属性 |\n\n## 注意事项\n\n1. **泛型类型**：`from __future__ import annotations` 是必需的，用于支持前向引用语法\n2. **线程安全**：`CyclicExecutor` 内部使用锁保护共享状态\n3. **状态不可变性**：建议状态对象设计为不可变或使用 Pydantic 的深拷贝机制\n4. **信号机制**：当前实现中 `signal` 参数默认为 `None`，可根据需要扩展\n\n---\n\n<a id='page-7'></a>\n\n## Search状态模块\n\n### 相关页面\n\n相关主题：[CoT状态模块](#page-8), [有限状态机模式](#page-6)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [cyclic_agent/search.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/search.py)\n- [cyclic_agent/state.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/state.py)\n- [cyclic_agent/__init__.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/__init__.py)\n- [cyclic_agent/executor.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n- [examples/bilibili_surfer/bilibili_surfer.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n- [examples/bilibili_surfer/fifo.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n</details>\n\n# Search状态模块\n\n## 概述\n\nSearch状态模块是CyclicAgent框架中用于封装搜索功能的核心组件。该模块通过继承`State`基类实现了一个专门处理搜索查询的状态类型，允许代理（Agent）在状态机中执行搜索操作并根据搜索结果进行状态转换。\n\nSearch模块采用了策略模式设计，`search`方法被声明为抽象方法（`NotImplementedError`），由子类实现具体的搜索逻辑。这种设计使得Search状态模块具有高度的灵活性和可扩展性，可以适配各种不同的搜索数据源和搜索API。 资料来源：[cyclic_agent/search.py:1-15]()\n\n## 架构设计\n\n### 类结构\n\n```mermaid\nclassDiagram\n    class State~SigT~ {\n        <<abstract>>\n        +next(signal: SigT | None) State\n    }\n    \n    class Search {\n        +query: str\n        +exit_: Callable\n        +next(signal: None) State\n        +search(query: str) str\n    }\n    \n    State <|-- Search : 继承\n```\n\nSearch类继承自`State[None]`基类，这意味着该状态的信号类型为`None`。状态在执行`next()`方法时不需要外部信号输入，而是直接执行内置的搜索逻辑。 资料来源：[cyclic_agent/state.py:1-18]()[cyclic_agent/search.py:5]()\n\n### 类型定义\n\n| 属性名 | 类型 | 说明 |\n|--------|------|------|\n| `query` | `str` | 搜索查询字符串，包含用户或代理要搜索的关键词 |\n| `exit_` | `Callable[[Annotated[str, \"search result\"]], State]` | 退出回调函数，接收搜索结果字符串作为参数，返回下一个状态 |\n\n回调函数的`Annotated`注解用于标记搜索结果的语义含义，便于类型检查和代码文档化。 资料来源：[cyclic_agent/search.py:6-7]()\n\n## 核心方法\n\n### next方法\n\n`next`方法是Search状态的状态转换实现。当执行器调用此方法时，会触发搜索操作并通过回调函数返回下一个状态。\n\n```mermaid\ngraph TD\n    A[执行器调用 next] --> B[执行 searchquery]\n    B --> C[获取搜索结果]\n    C --> D[调用 exit_ 回调]\n    D --> E[返回下一状态]\n```\n\n方法签名如下：\n\n```python\ndef next(self, signal: None = None) -> State:\n    search_result = self.search(self.query)\n    return self.exit_(search_result)\n```\n\n该方法接收一个可选的`signal`参数（类型为`None`），这是由于继承自泛型`State[None]`基类的接口要求。在实际执行中，`signal`参数不会被使用，搜索所需的查询内容已经存储在实例的`query`属性中。 资料来源：[cyclic_agent/search.py:9-12]()\n\n### search方法\n\n`search`方法是抽象搜索逻辑的占位符实现，设计者意图由子类重写此方法以提供具体的搜索功能。\n\n```python\ndef search(self, query: str) -> str:\n    raise NotImplementedError\n```\n\n该方法接收一个`query`字符串参数，返回搜索结果的字符串表示。在基类中直接抛出`NotImplementedError`异常，要求子类必须实现具体的搜索逻辑。开发者可以在子类中接入各种搜索服务，如全文搜索引擎、API调用、数据库查询等。 资料来源：[cyclic_agent/search.py:14-15]()\n\n## 使用模式\n\n### 基本集成流程\n\n在CyclicAgent框架中，Search状态通常与其他状态配合使用，形成完整的工作流。以下是在状态机中集成Search状态的典型模式：\n\n1. **定义Search子类**：继承`Search`类并实现`search`方法\n2. **配置退出回调**：在初始化时传入`exit_`回调函数，用于处理搜索结果\n3. **与执行器配合**：将Search状态作为初始状态或中间状态交给`CyclicExecutor`执行\n\n```mermaid\ngraph LR\n    A[其他状态] -->|转换| B[Search状态]\n    B -->|执行搜索| C[获取结果]\n    C -->|回调| D[下一状态]\n    D -->|循环| A\n```\n\n### 与Fifo内存组件配合\n\n在真实应用场景中（如B站冲浪示例），Search操作通常与`Fifo`内存组件配合使用。`Fifo`类实现了一个容量为100的先进先出队列，用于记录代理的历史行为：\n\n```python\nclass Fifo:\n    def __init__(self):\n        self.capacity = 100\n        self.queue = []\n        self.log_file = \"fifo_log.txt\"\n```\n\n每次执行搜索后，搜索关键词会被记录到内存中，帮助代理在后续决策时考虑历史上下文。 资料来源：[examples/bilibili_surfer/fifo.py:1-17]()\n\n### 实际应用示例\n\n在B站冲浪代理中，虽然没有直接继承`Search`类，但展示了类似的搜索模式实现：\n\n```python\nasync def search_by_type(response,\n                         search_type=search.SearchObjectType.VIDEO,\n                         order_type=search.OrderUser.FANS,\n                         order_sort=0):\n    # 实现B站视频搜索\n```\n\n代理通过生成搜索关键词、调用搜索API、解析结果、选择目标视频等步骤，形成完整的搜索-决策工作流。这种模式与Search状态模块的设计理念高度一致。 资料来源：[examples/bilibili_surfer/bilibili_surfer.py:1-120]()\n\n## 与框架其他组件的关系\n\n### 与State基类的关系\n\nSearch是`State`基类的具体实现，遵循状态模式的设计原则。每个状态必须实现`next`方法，该方法返回下一个要转换到的状态。Search类在`next`方法中嵌入了搜索执行逻辑，使得状态转换与业务逻辑紧密结合。 资料来源：[cyclic_agent/state.py:5-9]()\n\n### 与CyclicExecutor的关系\n\n`CyclicExecutor`负责管理和执行状态机的循环：\n\n```python\nclass CyclicExecutor:\n    def __init__(self, default_time_interval: float):\n        self.running = False\n        self.lock = threading.Lock()\n        self.default_time_interval = default_time_interval\n```\n\n执行器在每个时间间隔调用当前状态的`next`方法获取下一个状态，从而推动状态机向前运行。当Search状态被设置为当前状态时，执行器会触发其`next`方法执行搜索操作。 资料来源：[cyclic_agent/executor.py:1-40]()\n\n### 模块导出\n\nSearch类作为`cyclic_agent`包的一部分被导出，与核心组件`State`和`CyclicExecutor`一起构成框架的基础API：\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\n```\n\nSearch类本身未包含在`__all__`列表中，这可能意味着它被视为内部实现或需要直接从子模块导入：\n\n```python\nfrom cyclic_agent.search import Search\n```\n\n## 扩展指南\n\n### 实现自定义Search子类\n\n开发者可以通过继承Search类来实现特定数据源的搜索功能：\n\n```python\nfrom cyclic_agent.search import Search\nfrom cyclic_agent import State\n\nclass WebSearch(Search):\n    def search(self, query: str) -> str:\n        # 实现网络搜索逻辑\n        results = some_search_api.search(query)\n        return str(results)\n    \n    def handle_results(self, results: str) -> State:\n        # 处理搜索结果，决定下一状态\n        return SomeDecisionState(results=results)\n\n# 使用示例\ninitial_state = WebSearch(\n    query=\"Python最佳实践\",\n    exit_=lambda results: WebSearch(query=f\"关于{results}的详细信息\")\n)\n```\n\n### 集成外部搜索API\n\nSearch模块的灵活性使其可以与各种外部搜索服务集成：\n\n| 搜索服务 | 集成方式 | 适用场景 |\n|----------|----------|----------|\n| Elasticsearch | 同步HTTP请求 | 全文搜索 |\n| Algolia | SDK调用 | 应用内搜索 |\n| Bing/Google API | REST API | 网络搜索 |\n| 数据库全文索引 | SQL查询 | 结构化数据搜索 |\n\n## 设计理念\n\nSearch状态模块体现了CyclicAgent框架的几个核心设计原则：\n\n1. **状态即行为**：每个状态封装了特定的行为逻辑，搜索操作被建模为状态而非普通方法\n2. **回调驱动的状态转换**：通过`exit_`回调函数实现搜索结果与状态转换的解耦\n3. **抽象与实现分离**：`search`方法的抽象声明允许子类提供不同实现，保持框架核心稳定\n4. **有限状态机语义**：状态只能转换到`exit_`回调指定的下一状态，维持状态机的可预测性\n\n这种设计使得代理系统既能执行复杂的搜索任务，又能保持清晰的状态流转逻辑，便于调试和扩展。\n\n---\n\n<a id='page-8'></a>\n\n## CoT状态模块\n\n### 相关页面\n\n相关主题：[Search状态模块](#page-7)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [cyclic_agent/cot.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/cot.py)\n- [cyclic_agent/state.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/state.py)\n- [cyclic_agent/executor.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n- [cyclic_agent/__init__.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/__init__.py)\n- [examples/hello_world/hello_world.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/hello_world/hello_world.py)\n</details>\n\n# CoT状态模块\n\n## 概述\n\nCoT（Chain of Thought，思维链）状态模块是CyclicAgent框架中的一个核心组件，专门用于实现链式思维推理能力。该模块继承自基础`State`类，通过在提示词后附加\"Let's think step by step.\"指令，引导大语言模型（LLM）进行逐步推理，并将推理结果通过回调机制传递给下一个状态。\n\nCoT状态模块的设计遵循有限状态机（FSM）模式，允许在复杂的代理（Agent）工作流中无缝集成思维链推理能力。资料来源：[cyclic_agent/cot.py:1-18]()\n\n## 核心架构\n\n### 类定义与继承关系\n\n```\nState[SigT] (抽象基类)\n    └── CoT (思维链状态)\n```\n\n`CoT`类继承自`State[None]`，这意味着它是一个无信号类型的状态类。资料来源：[cyclic_agent/cot.py:5]()\n\n### 组件构成\n\n| 组件名称 | 类型 | 说明 |\n|---------|------|------|\n| `exit_` | `Callable[[str], State]` | 退出回调函数，接收LLM输出并返回下一个状态 |\n| `llm` | `State` | 底层LLM状态处理器，负责与语言模型交互 |\n| `prompt` | `str` | 用户提供的原始提示词 |\n\n资料来源：[cyclic_agent/cot.py:6-8]()\n\n## 工作原理\n\n### 思维链增强机制\n\n当`CoT`状态的`next()`方法被调用时，会自动对原始提示词进行思维链增强处理。具体流程如下：\n\n```python\ndef next(self, signal: None = None) -> State:\n    prompt = self.prompt + \"Let's think step by step.\"\n    \n    def callback(answer: str) -> State:\n        return self.exit_(answer)\n    \n    return self.llm(prompt=prompt, callback=callback)\n```\n\n1. **提示词增强**：将\"Let's think step by step.\"追加到原始`prompt`末尾\n2. **回调闭包**：创建一个内部`callback`函数，捕获`exit_`回调\n3. **状态传递**：将增强后的提示词和回调传递给底层LLM状态\n\n资料来源：[cyclic_agent/cot.py:10-17]()\n\n### 状态转换流程\n\n```mermaid\ngraph TD\n    A[CoT.next 调用] --> B[拼接思维链提示词]\n    B --> C[调用 LLM 处理]\n    C --> D[获取模型输出]\n    D --> E[触发 callback]\n    E --> F[执行 exit_ 回调]\n    F --> G[返回下一个 State]\n```\n\n## 与State基类的关系\n\n### 抽象基类定义\n\n`State`是一个使用Pydantic的`BaseModel`实现的泛型抽象类，定义了状态转换的核心接口：\n\n```python\nclass State[SigT](BaseModel):\n    @abstractmethod\n    def next(self, signal: SigT | None = None) -> State[SigT]:\n        \"\"\"Transition to the next state.\"\"\"\n        raise NotImplementedError\n```\n\n资料来源：[cyclic_agent/state.py:6-11]()\n\n### 接口契约\n\n| 方法 | 参数 | 返回值 | 说明 |\n|-----|------|--------|------|\n| `next` | `signal: SigT \\| None` | `State[SigT]` | 执行状态转换，返回下一个状态 |\n\n`CoT`类完整实现了这一接口，确保与CyclicExecutor执行器的兼容性。\n\n## 执行器集成\n\n`CyclicExecutor`负责管理和调度所有状态，包括`CoT`状态。执行器采用独立线程运行主循环，周期性地调用状态的`next()`方法：\n\n```python\ndef _main_loop(self, state: State) -> None:\n    while True:\n        if self.killed:\n            return\n\n        if self.running:\n            state = state.next()\n            time.sleep(self.default_time_interval)\n```\n\n资料来源：[cyclic_agent/executor.py:33-39]()\n\n### 执行流程图\n\n```mermaid\ngraph TD\n    A[CyclicExecutor.start] --> B[创建工作线程]\n    B --> C[_main_loop 运行]\n    C --> D{检查 running?}\n    D -->|否| E[等待]\n    E --> D\n    D -->|是| F[调用 state.next]\n    F --> G[获取下一个状态]\n    G --> H[休眠 default_time_interval]\n    H --> C\n```\n\n## 使用模式\n\n### 基础使用结构\n\n在实际应用中，`CoT`状态通常与其他自定义状态结合使用。以下是基于Hello World示例的典型模式：\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\nfrom cyclic_agent.cot import CoT\n\nclass MyLLM(State[None]):\n    prompt: str\n    callback: Callable[[str], State]\n    \n    def next(self, signal=None) -> State:\n        # 调用LLM API获取回答\n        response = llm.chat(message=self.prompt)\n        return self.callback(response.text)\n\nclass MyExitState(State[None]):\n    result: str\n    \n    def next(self, signal=None) -> State:\n        print(f\"最终结果: {self.result}\")\n        return self  # 或返回其他状态\n```\n\n### 回调机制详解\n\n`exit_`回调是连接CoT状态与下游处理的关键机制。它允许：\n\n- **动态状态路由**：根据LLM输出决定下一步状态\n- **上下文传递**：将推理结果携带到新状态\n- **条件分支**：实现复杂的条件逻辑\n\n## 模块导出\n\n`CoT`类通过`cyclic_agent.cot`模块导出，可通过以下方式导入：\n\n```python\nfrom cyclic_agent.cot import CoT\n```\n\n资料来源：[cyclic_agent/cot.py:1]()\n\n## 设计优势\n\n| 优势 | 说明 |\n|------|------|\n| **解耦设计** | CoT逻辑与LLM交互分离，便于单元测试 |\n| **可组合性** | 可与任何实现`State`接口的组件配合使用 |\n| **回调灵活性** | 允许外部控制状态转换逻辑 |\n| **框架兼容** | 无缝集成到CyclicExecutor状态机执行体系 |\n\n## 与其他状态的关系\n\n在CyclicAgent框架中，`CoT`状态与其他状态类型形成互补：\n\n```mermaid\ngraph LR\n    A[CoT] -->|思维链推理| B[普通State]\n    C[Search] -->|搜索增强| B\n    D[自定义状态] -->|领域逻辑| B\n    B --> E[CyclicExecutor]\n```\n\n- **CoT**：提供链式推理能力\n- **Search**：提供搜索增强能力\n- **自定义State**：处理特定业务逻辑\n\n## 总结\n\nCoT状态模块是CyclicAgent框架实现自主代理智能推理的核心组件。通过在提示词中嵌入思维链指令，该模块能够引导大语言模型进行更深入、更结构化的思考。结合状态机模式和回调机制，CoT状态为构建复杂、可扩展的AI代理系统提供了坚实的技术基础。\n\n---\n\n<a id='page-9'></a>\n\n## Hello World示例\n\n### 相关页面\n\n相关主题：[快速入门指南](#page-3), [Bilibili Surfer示例](#page-10)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [examples/hello_world/hello_world.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/hello_world/hello_world.py)\n- [cyclic_agent/state.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/state.py)\n- [cyclic_agent/executor.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n- [cyclic_agent/__init__.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/__init__.py)\n- [cyclic_agent/cot.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/cot.py)\n</details>\n\n# Hello World示例\n\n## 概述\n\nHello World示例是CyclicAgent框架的入门级演示项目，展示了如何使用状态机模式构建自主运行的AI代理。该示例创建了两个相互转换的状态，形成一个无限循环的问答系统。资料来源：[examples/hello_world/hello_world.py:1-27]()\n\n## 核心概念\n\n### 状态设计模式\n\nCyclicAgent将代理抽象为有限状态机（FSM），每个状态实现状态转换函数，返回另一个状态。这种设计允许状态转换操作无限进行，从而实现代理的“循环”特性。资料来源：[README.md:1-20]()\n\n### 状态基类\n\n所有状态必须继承`State`抽象基类，并实现`next()`方法。`State`类使用Pydantic的`BaseModel`，支持类型注解和自动验证。资料来源：[cyclic_agent/state.py:1-15]()\n\n## 系统架构\n\n### 组件关系图\n\n```mermaid\ngraph TD\n    A[AskQuestion 状态] -->|next()| B[AnswerQuestion 状态]\n    B -->|next()| A\n    C[CyclicExecutor] -->|管理执行| A\n    C -->|管理执行| B\n```\n\n### 类结构\n\n| 类名 | 文件位置 | 继承关系 | 职责 |\n|------|---------|---------|------|\n| `State` | cyclic_agent/state.py | BaseModel | 状态基类，定义`next()`抽象方法 |\n| `CyclicExecutor` | cyclic_agent/executor.py | - | 执行器，管理状态机的运行、暂停、终止 |\n| `AskQuestion` | examples/hello_world/hello_world.py | State[None] | 提问状态 |\n| `AnswerQuestion` | examples/hello_world/hello_world.py | State[None] | 回答状态 |\n\n## 状态实现详解\n\n### AskQuestion状态\n\n```python\nclass AskQuestion(State[None]):\n    def next(self, signal: None = None) -> AnswerQuestion:\n        response = co.chat(message=\"Ask a question\", temperature=1)\n        print(response.text)\n        return AnswerQuestion(question=response.text)\n```\n\n该状态负责生成问题，使用Cohere API进行对话生成，温度参数设为1以获得更具创造性的输出。状态转换到`AnswerQuestion`，携带生成的问题内容。资料来源：[examples/hello_world/hello_world.py:17-22]()\n\n### AnswerQuestion状态\n\n```python\nclass AnswerQuestion(State[None]):\n    question: str\n\n    def next(self, signal: None = None) -> AskQuestion:\n        answer = co.chat(message=self.question)\n        print(answer)\n        return AskQuestion()\n```\n\n该状态持有问题内容字段`question`，使用Cohere API获取回答后，转换回`AskQuestion`状态，形成循环。资料来源：[examples/hello_world/hello_world.py:24-30]()\n\n## CyclicExecutor执行器\n\n### 核心功能\n\n`CyclicExecutor`类负责在独立线程中运行状态机，支持运行控制操作。资料来源：[cyclic_agent/executor.py:1-42]()\n\n| 方法 | 功能描述 |\n|------|---------|\n| `start(initial_state)` | 启动执行器，使用独立线程运行状态机 |\n| `pause()` | 暂停状态转换 |\n| `resume()` | 恢复状态转换 |\n| `kill()` | 终止执行器 |\n\n### 执行流程\n\n```mermaid\nsequenceDiagram\n    participant User\n    participant Executor\n    participant State\n    \n    User->>Executor: start(initial_state)\n    loop 状态循环\n        Executor->>State: state.next()\n        State-->>Executor: next_state\n        Executor->>Executor: sleep(default_time_interval)\n    end\n    User->>Executor: kill()\n```\n\n### 线程管理实现\n\n执行器使用`threading.Thread`在后台线程中运行主循环，通过锁机制确保线程安全的状态控制。资料来源：[cyclic_agent/executor.py:16-23]()\n\n## 配置与环境\n\n### 依赖项\n\n| 依赖包 | 用途 |\n|-------|------|\n| cohere | LLM对话API客户端 |\n| python-dotenv | 环境变量管理 |\n| cyclic_agent | 核心框架 |\n\n### 环境变量\n\n| 变量名 | 说明 |\n|-------|------|\n| COHERE_API_KEY | Cohere API密钥 |\n\n```python\nfrom dotenv import load_dotenv\nload_dotenv()\nco = cohere.Client(os.environ.get(\"COHERE_API_KEY\"))\n```\n\n资料来源：[examples/hello_world/hello_world.py:7-10]()\n\n## 运行示例\n\n### 代码\n\n```python\nif __name__ == \"__main__\":\n    initial_state = AskQuestion()\n    executor = CyclicExecutor(5)\n    executor.start(initial_state)\n    time.sleep(20)\n```\n\n### 参数说明\n\n| 参数 | 值 | 说明 |\n|------|-----|------|\n| default_time_interval | 5 | 每次状态转换间隔5秒 |\n| sleep时间 | 20 | 程序运行20秒后退出 |\n\n## 进阶示例参考\n\n除了Hello World示例外，仓库还提供了更复杂的示例：\n\n| 示例名称 | 文件路径 | 特性 |\n|---------|---------|------|\n| Chain of Thought | cyclic_agent/cot.py | 思维链模式 |\n| Search | cyclic_agent/search.py | 搜索功能封装 |\n| Bilibili冲浪者 | examples/bilibili_surfer/ | 完整代理实现 |\n\n### CoT（思维链）示例\n\n`CoT`类展示了如何实现思维链模式，通过在提示词后添加\"Let's think step by step.\"引导模型分步骤推理。资料来源：[cyclic_agent/cot.py:1-16]()\n\n## 总结\n\nHello World示例演示了CyclicAgent框架的核心用法：\n\n1. **状态定义**：继承`State`基类，实现`next()`方法\n2. **状态转换**：通过`next()`方法返回下一个状态\n3. **执行管理**：使用`CyclicExecutor`控制状态机运行\n4. **无限循环**：状态间相互转换形成闭环\n\n该框架的核心理念是将AI代理建模为有限状态机，每个状态根据内部属性和外部信号推理下一状态，实现自主、循环的代理行为。\n\n---\n\n<a id='page-10'></a>\n\n## Bilibili Surfer示例\n\n### 相关页面\n\n相关主题：[Hello World示例](#page-9)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [examples/bilibili_surfer/bilibili_surfer.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n- [examples/bilibili_surfer/fifo.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n- [cyclic_agent/state.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/state.py)\n- [cyclic_agent/executor.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n- [cyclic_agent/__init__.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/__init__.py)\n</details>\n\n# Bilibili Surfer示例\n\n## 概述\n\nBilibili Surfer是cyclic-agent框架的一个完整示例应用，演示了如何构建一个自主运行的AI代理，使其能够像真实用户一样浏览Bilibili视频网站、阅读评论并自动回复。该示例展示了有限状态机（FSM）设计模式在实际应用中的强大能力，将AI代理的行为抽象为多个可相互转换的状态，每个状态根据内部属性和外部信号推断下一个状态。\n\n这个示例的核心价值在于它演示了如何将复杂的AI行为与外部API集成。通过结合Cohere大语言模型和Bilibili API，系统能够理解自然语言指令，做出合理的决策，并在视频网站上执行实际操作。整个系统运行在CyclicExecutor的调度下，按照预设的时间间隔不断循环执行状态转换，直到达到预设的迭代次数或被手动终止。\n\n## 系统架构\n\n### 整体架构图\n\n```mermaid\ngraph TD\n    A[CyclicExecutor] -->|启动| B[BrowsingVideo状态]\n    B -->|搜索视频| C{LLM决策}\n    C -->|BrowsingVideo| B\n    C -->|ReadingComments| D[ReadingComments状态]\n    D -->|选择评论| C\n    C -->|PostComment| E[PostComment状态]\n    E -->|完成回复| B\n    B -->|记录| F[Fifo内存]\n    D -->|记录| F\n    E -->|记录| F\n```\n\n### 核心组件层次\n\n系统采用分层架构设计，从底层到顶层依次为：\n\n1. **核心框架层**（cyclic_agent包）\n   - `State`基类：定义所有状态的抽象接口\n   - `CyclicExecutor`：状态机执行器，负责驱动状态循环\n   - `Search`、`CoT`等辅助组件\n\n2. **基础服务层**\n   - `Fifo`：内存管理组件，持久化记录代理行为历史\n   - Bilibili API集成：通过bilibili_api库访问B站服务\n\n3. **业务逻辑层**\n   - `BilibiliStateBase`：所有业务状态的基类\n   - `BrowsingVideo`、`ReadingComments`、`PostComment`：具体业务状态\n\n4. **AI决策层**\n   - Cohere Client：大语言模型集成\n   - 提示词模板：指导AI做出合理的决策\n\n## 状态机设计\n\n### 状态定义\n\n系统定义了三种主要状态，每种状态都继承自`BilibiliStateBase`，而`BilibiliStateBase`又继承自`State[None]`基类。\n\n| 状态类名 | 功能描述 | 主要属性 |\n|---------|---------|---------|\n| `BrowsingVideo` | 搜索并浏览视频 | 无特殊属性，继承基类属性 |\n| `ReadingComments` | 阅读视频下的热门评论 | `video_bvid`、`video_title`、`video_description` |\n| `PostComment` | 回复选定的评论 | 包含`reply_to`、`reply_to_oid`用于定位回复目标 |\n\n### 状态转换关系\n\n```mermaid\nstateDiagram-v2\n    [*] --> BrowsingVideo\n    BrowsingVideo --> BrowsingVideo: 返回继续浏览\n    BrowsingVideo --> ReadingComments: 选择评论\n    ReadingComments --> BrowsingVideo: 返回视频浏览\n    ReadingComments --> ReadingComments: 继续读评论\n    ReadingComments --> PostComment: 选择回复\n    PostComment --> BrowsingVideo: 完成回复\n```\n\n### 类型别名定义\n\n为了确保状态转换的类型安全，系统使用Python的类型别名（`type`语句）定义每个状态可到达的下一个状态：\n\n```python\ntype BrowsingVideoReachable = Union[BrowsingVideo, ReadingComments]\ntype ReadingCommentsReachable = Union[BrowsingVideo, ReadingComments, PostComment]\ntype PostCommentReachable = Union[BrowsingVideo]\n```\n\n这种设计确保了编译时就能发现无效的状态转换，防止运行时错误。\n\n## 核心类详解\n\n### BilibiliStateBase\n\n`BilibiliStateBase`是所有Bilibili相关状态的抽象基类，它封装了状态机运行所需的所有共享资源和通用逻辑。\n\n```python\nclass BilibiliStateBase(State[None], ABC):\n    model_config = ConfigDict(arbitrary_types_allowed=True)\n    initial_prompt: str\n    memory: Fifo\n    co: Client\n    credential: Credential\n```\n\n**属性说明**：\n\n| 属性名 | 类型 | 用途 |\n|-------|------|------|\n| `initial_prompt` | str | 初始提示词，定义AI的角色和行为准则 |\n| `memory` | Fifo | 先进先出内存，存储历史行为记录 |\n| `co` | Client | Cohere客户端，用于调用大语言模型 |\n| `credential` | Credential | Bilibili API凭证，包含SESSDATA、BILI_JCT、BUVID3 |\n\n**核心方法**：`_infer_state_helper`方法使用LLM来决定下一个状态。当调用此方法时，会向LLM传递当前状态描述、历史行为记录以及可选的下一个状态列表，LLM返回的文本与预定义的选项进行模式匹配，从而决定状态转换的方向。\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:43-58]()\n\n### BrowsingVideo状态\n\n`BrowsingVideo`是系统的入口状态，负责视频搜索和浏览功能。\n\n```python\nclass BrowsingVideo(BilibiliStateBase):\n    @overrides\n    def next(self, signal: None = None) -> BrowsingVideoReachable:\n        # 1. 生成搜索关键词\n        prompt = I(f\"\"\"{self.initial_prompt}...Generate a keyword phrase...\"\"\")\n        response = self.co.chat(temperature=1, message=prompt).text\n        \n        # 2. 调用B站搜索API\n        res = asyncio.run(search.search_by_type(...))\n        self.memory.add(f\"searched for {response}\")\n        \n        # 3. 获取Top10视频供选择\n        top_10 = [...]\n        \n        # 4. 让LLM选择视频\n        video = res['result'][int(response)]\n        self.memory.add(f\"finds {video['title']}\")\n        \n        # 5. 决定下一步\n        return self._infer_state_helper('BrowsingVideo', 'ReadingComments')\n```\n\n该状态的工作流程包括：使用LLM生成创造性的搜索关键词避免重复；调用B站API按粉丝数排序搜索视频；将Top10视频列表展示给LLM供选择；根据`_infer_state_helper`的决策结果决定是继续浏览还是转向评论阅读。\n\n### ReadingComments状态\n\n`ReadingComments`状态专注于视频评论的阅读和选择。当系统处于此状态时，会获取指定视频的热门评论并展示给LLM进行选择。\n\n```python\nclass ReadingComments(BilibiliStateBase):\n    video_bvid: str\n    video_title: str\n    video_description: str\n\n    @overrides\n    def next(self, signal: None = None) -> ReadingCommentsReachable:\n        c = asyncio.run(comment.get_comments(...))\n        top_10 = []\n        for i in range(min(5, c['page']['count'])):\n            cmt = c['replies'][i]\n            top_10.append(f\"{i + 1} {cmt['member']['uname']}: {cmt['content']['message']}\")\n        \n        # 选择评论后决定下一步\n        match self._infer_state_helper('BrowsingVideo', 'ReadingComments', 'PostComment'):\n            case 'BrowsingVideo':\n                return BrowsingVideo(...)\n            case 'ReadingComments':\n                return self\n            case 'PostComment':\n                return PostComment(...)\n```\n\n### PostComment状态\n\n`PostComment`是系统的执行状态，负责生成并发送评论回复。\n\n```python\nclass PostComment(BilibiliStateBase):\n    video_bvid: str\n    video_title: str\n    video_description: str\n    reply_to: str | None\n    reply_to_oid: int | None\n\n    @overrides\n    def next(self, signal: None = None) -> PostCommentReachable:\n        if self.reply_to:\n            prompt = I(f\"\"\"You are replying to a comment: {self.reply_to}...\"\"\")\n            response = self.co.chat(temperature=1, message=prompt).text\n            footnote = f\"\\nI am a bot, contact {os.getenv('name')}...\"\n            \n            # 发送评论\n            asyncio.run(comment.send_comment(...))\n            self.memory.add(f\"commented {response} to {self.video_title}\")\n            \n            # 发布动态\n            asyncio.run(dynamic.send_dynamic(...))\n        \n        return BrowsingVideo(...)\n```\n\n该状态的亮点在于：生成回复后会自动附加免责声明；评论发送成功后会在个人动态中同步发布；无论是否需要回复，都会返回`BrowsingVideo`状态继续新的浏览循环。\n\n## 内存管理系统\n\n### Fifo类设计\n\n`Fifo`（First-In-First-Out）类是一个轻量级的内存管理组件，用于记录AI代理的所有历史行为。\n\n```python\nclass Fifo:\n    def __init__(self):\n        self.capacity = 100\n        self.queue = []\n        self.log_file = \"fifo_log.txt\"\n        if not os.path.exists(self.log_file):\n            with open(self.log_file, 'w') as file:\n                file.write(\"\")\n```\n\n**主要特性**：\n\n| 特性 | 说明 |\n|-----|------|\n| 容量限制 | 最多存储100条记录，超出后自动移除最旧的记录 |\n| 时间戳 | 每条记录都带有精确到秒的时间戳 |\n| 持久化 | 所有操作都会追加写入`fifo_log.txt`日志文件 |\n| 提示生成 | `prompt()`方法返回格式化的历史记录供LLM参考 |\n\n**核心方法**：\n\n```python\ndef add(self, item):\n    if not isinstance(item, str):\n        raise ValueError(\"Only strings can be added to the FIFO\")\n    if len(self.queue) >= self.capacity:\n        self.queue.pop(0)  # 移除最旧的记录\n    timestamp = datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n    self.queue.append((item, timestamp))\n    self.log_to_file(item, timestamp)\n\ndef prompt(self):\n    return \"\\n\".join([f\"{time} - {text}\" for text, time in reversed(self.queue)])\n```\n\n### 内存数据流\n\n```mermaid\ngraph LR\n    A[状态执行] -->|add| B[Fifo队列]\n    B -->|prompt| C[LLM提示词]\n    C -->|决策| D[下一状态]\n    B -->|log_to_file| E[fifo_log.txt]\n```\n\n内存系统在状态转换中扮演着至关重要的角色。每个状态的`next`方法都会调用`memory.add()`记录当前行为，而`_infer_state_helper`方法会调用`memory.prompt()`获取历史记录并包含在LLM提示词中，使AI能够基于过去的决策历史做出更加连贯和智能的选择。\n\n## 执行器机制\n\n### CyclicExecutor工作原理\n\n`CyclicExecutor`是驱动整个状态机运转的核心执行器，采用多线程架构实现状态循环。\n\n```python\nclass CyclicExecutor:\n    def __init__(self, default_time_interval: float):\n        self.running = False\n        self.lock = threading.Lock()\n        self.default_time_interval = default_time_interval\n        self.killed = False\n        self.thread = None\n```\n\n**线程安全设计**：执行器使用`threading.Lock`来保护`running`和`killed`状态标志，确保在多线程环境下状态切换的安全性。`pause()`和`resume()`方法允许在运行时暂停和恢复执行，而`kill()`方法则可以干净地终止整个循环。\n\n### 主循环逻辑\n\n```python\ndef _main_loop(self, state: State) -> None:\n    while True:\n        if self.killed:\n            return\n        \n        if self.running:\n            state = state.next()\n            time.sleep(self.default_time_interval)\n```\n\n主循环采用经典的\"检查-执行-休眠\"模式：每次迭代检查是否被终止或暂停；如果正常运行则调用当前状态的`next()`方法获取下一个状态；然后根据预设的时间间隔进行休眠，控制状态转换的频率。\n\n### 示例启动流程\n\n```python\nif __name__ == \"__main__\":\n    initial_prompt = \"You are a dude browsing Bilibili...\"\n    \n    initial_state = BrowsingVideo(\n        memory=Fifo(),\n        initial_prompt=initial_prompt,\n        co=Client(os.environ.get(\"COHERE_API_KEY\")),\n        credential=Credential(\n            sessdata=SESSDATA,\n            bili_jct=BILI_JCT,\n            buvid3=BUVID3\n        )\n    )\n    executor = CyclicExecutor(5)\n    executor.start(initial_state)\n    time.sleep(1000)\n```\n\n启动时需要准备：FIFO内存实例供状态共享；定义AI角色的初始提示词；配置Bilibili API凭证；创建执行器并传入初始状态。执行器会在后台线程中运行，主线程可以继续执行其他操作或使用`sleep`控制运行时间。\n\n## 环境配置\n\n### 必需的环境变量\n\n系统运行需要配置以下环境变量，通常通过`.env`文件管理：\n\n| 变量名 | 来源 | 用途 |\n|-------|------|------|\n| `COHERE_API_KEY` | Cohere官网 | 调用Cohere大语言模型 |\n| `SESSDATA` | Bilibili网站 | 用户会话认证 |\n| `BILI_JCT` | Bilibili网站 | CSRF令牌 |\n| `BUVID3` | Bilibili网站 | 设备标识 |\n| `name` | 自定义 | 机器人联系信息（用于自动回复的免责声明） |\n\n### 依赖库\n\n```python\nfrom bilibili_api import search, Credential, comment, video, dynamic\nfrom bilibili_api.comment import OrderType, CommentResourceType\nfrom bilibili_api.dynamic import BuildDynamic\nfrom cohere import Client\nfrom overrides import overrides\nfrom pydantic import ConfigDict\n```\n\n主要依赖包括：`bilibili_api`提供B站API封装；`cohere`用于LLM交互；`pydantic`处理数据模型验证；`overrides`确保方法正确重写父类接口。\n\n## 设计模式应用\n\n### 状态设计模式\n\n整个系统建立在GoF的状态设计模式之上。每个具体状态类（如`BrowsingVideo`）都封装了特定状态下的行为和状态转换逻辑，状态之间通过`next()`方法返回下一个状态对象来实现无缝切换。这种设计避免了大型条件语句，使新增状态类型变得简单——只需定义新的状态类并实现`next()`方法即可。\n\n### 工厂模式暗示\n\n虽然代码中没有显式的工厂类，但`next()`方法实际上充当了状态工厂的角色。每个状态根据当前上下文\"生产\"出下一个状态对象，决定系统的后续走向。这种隐式工厂模式与状态模式紧密结合，形成了灵活的状态转换机制。\n\n### 策略模式暗示\n\n`_infer_state_helper`方法可以被视为策略模式的应用。不同的状态可以根据需要传入不同的可选状态列表，LLM的决策策略可以被替换为其他实现（如基于规则的决策），而不影响状态类的整体结构。\n\n## 扩展与定制\n\n### 添加新状态\n\n要添加新的业务状态，需要：\n\n1. 创建新的状态类继承`BilibiliStateBase`\n2. 实现`next()`方法定义状态行为\n3. 定义可达状态类型别名\n4. 在相关状态中添加对该新状态的转换选项\n\n### 替换AI模型\n\n当前使用Cohere作为AI后端，如需替换为其他LLM（如OpenAI GPT），只需：\n\n1. 修改导入语句\n2. 替换`Client`实例化方式\n3. 调整API调用参数（确保参数语义兼容）\n\n### 调整运行参数\n\n| 参数 | 位置 | 说明 |\n|-----|------|------|\n| 状态转换间隔 | `CyclicExecutor(5)` | 5秒，可调整执行频率 |\n| 内存容量 | `Fifo.capacity` | 默认100条记录 |\n| 搜索结果数量 | `range(10)` | 获取Top10视频 |\n| 评论展示数量 | `min(5, ...)` | 显示5条热门评论 |\n\n## 总结\n\nBilibili Surfer示例完整展示了cyclic-agent框架在实际应用中的使用方法。通过有限状态机将复杂的AI行为分解为清晰的状态单元，结合大语言模型实现智能决策，再配合外部API执行实际操作，整个系统能够自主、连续地在Bilibili网站上执行浏览、评论和回复等任务。这个示例不仅是一个可运行的演示程序，更是一个展示AI Agent设计最佳实践的教学案例，为开发者构建自己的AI代理应用提供了完整的参考模板。\n\n---\n\n---\n\n## Doramagic 踩坑日志\n\n项目：xingjianll/cyclic-agent\n\n摘要：发现 6 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：能力坑 - 能力判断依赖假设。\n\n## 1. 能力坑 · 能力判断依赖假设\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：README/documentation is current enough for a first validation pass.\n- 对用户的影响：假设不成立时，用户拿不到承诺的能力。\n- 建议检查：将假设转成下游验证清单。\n- 防护动作：假设必须转成验证项；没有验证结果前不能写成事实。\n- 证据：capability.assumptions | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | README/documentation is current enough for a first validation pass.\n\n## 2. 维护坑 · 维护活跃度未知\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：未记录 last_activity_observed。\n- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。\n- 建议检查：补 GitHub 最近 commit、release、issue/PR 响应信号。\n- 防护动作：维护活跃度未知时，推荐强度不能标为高信任。\n- 证据：evidence.maintainer_signals | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | last_activity_observed missing\n\n## 3. 安全/权限坑 · 下游验证发现风险项\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：no_demo\n- 对用户的影响：下游已经要求复核，不能在页面中弱化。\n- 建议检查：进入安全/权限治理复核队列。\n- 防护动作：下游风险存在时必须保持 review/recommendation 降级。\n- 证据：downstream_validation.risk_items | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | no_demo; severity=medium\n\n## 4. 安全/权限坑 · 存在评分风险\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：no_demo\n- 对用户的影响：风险会影响是否适合普通用户安装。\n- 建议检查：把风险写入边界卡，并确认是否需要人工复核。\n- 防护动作：评分风险必须进入边界卡，不能只作为内部分数。\n- 证据：risks.scoring_risks | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | no_demo; severity=medium\n\n## 5. 维护坑 · issue/PR 响应质量未知\n\n- 严重度：low\n- 证据强度：source_linked\n- 发现：issue_or_pr_quality=unknown。\n- 对用户的影响：用户无法判断遇到问题后是否有人维护。\n- 建议检查：抽样最近 issue/PR，判断是否长期无人处理。\n- 防护动作：issue/PR 响应未知时，必须提示维护风险。\n- 证据：evidence.maintainer_signals | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | issue_or_pr_quality=unknown\n\n## 6. 维护坑 · 发布节奏不明确\n\n- 严重度：low\n- 证据强度：source_linked\n- 发现：release_recency=unknown。\n- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。\n- 建议检查：确认最近 release/tag 和 README 安装命令是否一致。\n- 防护动作：发布节奏未知或过期时，安装说明必须标注可能漂移。\n- 证据：evidence.maintainer_signals | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | release_recency=unknown\n\n<!-- canonical_name: xingjianll/cyclic-agent; human_manual_source: deepwiki_human_wiki -->\n",
      "markdown_key": "cyclic-agent",
      "pages": "draft",
      "source_refs": [
        {
          "evidence_id": "art_2a2d1b4b3cfd487880b7144fa08bc9e2",
          "kind": "docs",
          "supports_claim_ids": [
            "claim_identity",
            "claim_distribution",
            "claim_capability"
          ],
          "url": "https://github.com/xingjianll/cyclic-agent#readme"
        }
      ],
      "summary": "DeepWiki/Human Wiki 完整输出，末尾追加 Discovery Agent 踩坑日志。",
      "title": "cyclic-agent 说明书",
      "toc": [
        "https://github.com/xingjianll/cyclic-agent 项目说明书",
        "目录",
        "项目介绍",
        "1 项目概述",
        "2 核心设计理念",
        "3 核心组件",
        "4 工作流程",
        "启动执行器",
        "Doramagic 踩坑日志"
      ]
    }
  },
  "quality_gate": {
    "blocking_gaps": [],
    "category_confidence": "medium",
    "compile_status": "ready_for_review",
    "five_assets_present": true,
    "install_sandbox_verified": true,
    "missing_evidence": [],
    "next_action": "publish to Doramagic.ai project surfaces",
    "prompt_preview_boundary_ok": true,
    "publish_status": "publishable",
    "quick_start_verified": true,
    "repo_clone_verified": true,
    "repo_commit": "40af271a355887f812da43bb45f82c35af4e2508",
    "repo_inspection_error": null,
    "repo_inspection_files": [
      "pyproject.toml",
      "README.md",
      "examples/hello_world/hello_world.py",
      "examples/hello_world/__init__.py",
      "examples/bilibili_surfer/bilibili_surfer.py",
      "examples/bilibili_surfer/__init__.py",
      "examples/bilibili_surfer/fifo.py"
    ],
    "repo_inspection_verified": true,
    "review_reasons": [
      "community_discussion_evidence_below_public_threshold"
    ],
    "tag_count_ok": true,
    "unsupported_claims": []
  },
  "schema_version": "0.1",
  "user_assets": {
    "ai_context_pack": {
      "asset_id": "ai_context_pack",
      "filename": "AI_CONTEXT_PACK.md",
      "markdown": "# cyclic-agent - Doramagic AI Context Pack\n\n> 定位：安装前体验与判断资产。它帮助宿主 AI 有一个好的开始，但不代表已经安装、执行或验证目标项目。\n\n## 充分原则\n\n- **充分原则，不是压缩原则**：AI Context Pack 应该充分到让宿主 AI 在开工前理解项目价值、能力边界、使用入口、风险和证据来源；它可以分层组织，但不以最短摘要为目标。\n- **压缩策略**：只压缩噪声和重复内容，不压缩会影响判断和开工质量的上下文。\n\n## 给宿主 AI 的使用方式\n\n你正在读取 Doramagic 为 cyclic-agent 编译的 AI Context Pack。请把它当作开工前上下文：帮助用户理解适合谁、能做什么、如何开始、哪些必须安装后验证、风险在哪里。不要声称你已经安装、运行或执行了目标项目。\n\n## Claim 消费规则\n\n- **事实来源**：Repo Evidence + Claim/Evidence Graph；Human Wiki 只提供显著性、术语和叙事结构。\n- **事实最低状态**：`supported`\n- `supported`：可以作为项目事实使用，但回答中必须引用 claim_id 和证据路径。\n- `weak`：只能作为低置信度线索，必须要求用户继续核实。\n- `inferred`：只能用于风险提示或待确认问题，不能包装成项目事实。\n- `unverified`：不得作为事实使用，应明确说证据不足。\n- `contradicted`：必须展示冲突来源，不得替用户强行选择一个版本。\n\n## 它最适合谁\n\n- **想在安装前理解开源项目价值和边界的用户**：当前证据主要来自项目文档。 证据：`README.md` Claim：`clm_0002` supported 0.86\n\n## 它能做什么\n\n- **命令行启动或安装流程**（需要安装后验证）：项目文档中存在可执行命令，真实使用需要在本地或宿主环境中运行这些命令。 证据：`README.md` Claim：`clm_0001` supported 0.86\n\n## 怎么开始\n\n- `pip install cyclic-agent` 证据：`README.md` Claim：`clm_0003` supported 0.86\n\n## 继续前判断卡\n\n- **当前建议**：需要管理员/安全审批\n- **为什么**：继续前可能涉及密钥、账号、外部服务或敏感上下文，建议先经过管理员或安全审批。\n\n### 30 秒判断\n\n- **现在怎么做**：需要管理员/安全审批\n- **最小安全下一步**：先跑 Prompt Preview；若涉及凭证或企业环境，先审批再试装\n- **先别相信**：真实输出质量不能在安装前相信。\n- **继续会触碰**：命令执行、本地环境或项目文件、环境变量 / API Key\n\n### 现在可以相信\n\n- **适合人群线索：想在安装前理解开源项目价值和边界的用户**（supported）：有 supported claim 或项目证据支撑，但仍不等于真实安装效果。 证据：`README.md` Claim：`clm_0002` supported 0.86\n- **能力存在：命令行启动或安装流程**（supported）：可以相信项目包含这类能力线索；是否适合你的具体任务仍要试用或安装后验证。 证据：`README.md` Claim：`clm_0001` supported 0.86\n- **存在 Quick Start / 安装命令线索**（supported）：可以相信项目文档出现过启动或安装入口；不要因此直接在主力环境运行。 证据：`README.md` Claim：`clm_0003` supported 0.86\n\n### 现在还不能相信\n\n- **真实输出质量不能在安装前相信。**（unverified）：Prompt Preview 只能展示引导方式，不能证明真实项目中的结果质量。\n- **宿主 AI 版本兼容性不能在安装前相信。**（unverified）：Claude、Cursor、Codex、Gemini 等宿主加载规则和版本差异必须在真实环境验证。\n- **不会污染现有宿主 AI 行为，不能直接相信。**（inferred）：Skill、plugin、AGENTS/CLAUDE/GEMINI 指令可能改变宿主 AI 的默认行为。\n- **可安全回滚不能默认相信。**（unverified）：除非项目明确提供卸载和恢复说明，否则必须先在隔离环境验证。\n- **真实安装后是否与用户当前宿主 AI 版本兼容？**（unverified）：兼容性只能通过实际宿主环境验证。\n- **项目输出质量是否满足用户具体任务？**（unverified）：安装前预览只能展示流程和边界，不能替代真实评测。\n- **安装命令是否需要网络、权限或全局写入？**（unverified）：这影响企业环境和个人环境的安装风险。 证据：`README.md`\n\n### 继续会触碰什么\n\n- **命令执行**：包管理器、网络下载、本地插件目录、项目配置或用户主目录。 原因：运行第一条命令就可能产生环境改动；必须先判断是否值得跑。 证据：`README.md`\n- **本地环境或项目文件**：安装结果、插件缓存、项目配置或本地依赖目录。 原因：安装前无法证明写入范围和回滚方式，需要隔离验证。 证据：`README.md`\n- **环境变量 / API Key**：项目入口文档明确出现 API key、token、secret 或账号凭证配置。 原因：如果真实安装需要凭证，应先使用测试凭证并经过权限/合规判断。 证据：`README.md`, `examples/bilibili_surfer/bilibili_surfer.py`, `examples/hello_world/hello_world.py`\n- **宿主 AI 上下文**：AI Context Pack、Prompt Preview、Skill 路由、风险规则和项目事实。 原因：导入上下文会影响宿主 AI 后续判断，必须避免把未验证项包装成事实。\n\n### 最小安全下一步\n\n- **先跑 Prompt Preview**：用安装前交互式试用判断工作方式是否匹配，不需要授权或改环境。（适用：任何项目都适用，尤其是输出质量未知时。）\n- **只在隔离目录或测试账号试装**：避免安装命令污染主力宿主 AI、真实项目或用户主目录。（适用：存在命令执行、插件配置或本地写入线索时。）\n- **不要使用真实生产凭证**：环境变量/API key 一旦进入宿主或工具链，可能产生账号和合规风险。（适用：出现 API、TOKEN、KEY、SECRET 等环境线索时。）\n- **安装后只验证一个最小任务**：先验证加载、兼容、输出质量和回滚，再决定是否深用。（适用：准备从试用进入真实工作流时。）\n\n### 退出方式\n\n- **保留安装前状态**：记录原始宿主配置和项目状态，后续才能判断是否可恢复。\n- **记录安装命令和写入路径**：没有明确卸载说明时，至少要知道哪些目录或配置需要手动清理。\n- **准备撤销测试 API key 或 token**：测试凭证泄露或误用时，可以快速止损。\n- **如果没有回滚路径，不进入主力环境**：不可回滚是继续前阻断项，不应靠信任或运气继续。\n\n## 哪些只能预览\n\n- 解释项目适合谁和能做什么\n- 基于项目文档演示典型对话流程\n- 帮助用户判断是否值得安装或继续研究\n\n## 哪些必须安装后验证\n\n- 真实安装 Skill、插件或 CLI\n- 执行脚本、修改本地文件或访问外部服务\n- 验证真实输出质量、性能和兼容性\n\n## 边界与风险判断卡\n\n- **把安装前预览误认为真实运行**：用户可能高估项目已经完成的配置、权限和兼容性验证。 处理方式：明确区分 prompt_preview_can_do 与 runtime_required。 Claim：`clm_0004` inferred 0.45\n- **命令执行会修改本地环境**：安装命令可能写入用户主目录、宿主插件目录或项目配置。 处理方式：先在隔离环境或测试账号中运行。 证据：`README.md` Claim：`clm_0005` supported 0.86\n- **待确认**：真实安装后是否与用户当前宿主 AI 版本兼容？。原因：兼容性只能通过实际宿主环境验证。\n- **待确认**：项目输出质量是否满足用户具体任务？。原因：安装前预览只能展示流程和边界，不能替代真实评测。\n- **待确认**：安装命令是否需要网络、权限或全局写入？。原因：这影响企业环境和个人环境的安装风险。\n\n## 开工前工作上下文\n\n### 加载顺序\n\n- 先读取 how_to_use.host_ai_instruction，建立安装前判断资产的边界。\n- 读取 claim_graph_summary，确认事实来自 Claim/Evidence Graph，而不是 Human Wiki 叙事。\n- 再读取 intended_users、capabilities 和 quick_start_candidates，判断用户是否匹配。\n- 需要执行具体任务时，优先查 role_skill_index，再查 evidence_index。\n- 遇到真实安装、文件修改、网络访问、性能或兼容性问题时，转入 risk_card 和 boundaries.runtime_required。\n\n### 任务路由\n\n- **命令行启动或安装流程**：先说明这是安装后验证能力，再给出安装前检查清单。 边界：必须真实安装或运行后验证。 证据：`README.md` Claim：`clm_0001` supported 0.86\n\n### 上下文规模\n\n- 文件总数：15\n- 重要文件覆盖：9/15\n- 证据索引条目：9\n- 角色 / Skill 条目：1\n\n### 证据不足时的处理\n\n- **missing_evidence**：说明证据不足，要求用户提供目标文件、README 段落或安装后验证记录；不要补全事实。\n- **out_of_scope_request**：说明该任务超出当前 AI Context Pack 证据范围，并建议用户先查看 Human Manual 或真实安装后验证。\n- **runtime_request**：给出安装前检查清单和命令来源，但不要替用户执行命令或声称已执行。\n- **source_conflict**：同时展示冲突来源，标记为待核实，不要强行选择一个版本。\n\n## Prompt Recipes\n\n### 适配判断\n\n- 目标：判断这个项目是否适合用户当前任务。\n- 预期输出：适配结论、关键理由、证据引用、安装前可预览内容、必须安装后验证内容、下一步建议。\n\n```text\n请基于 cyclic-agent 的 AI Context Pack，先问我 3 个必要问题，然后判断它是否适合我的任务。回答必须包含：适合谁、能做什么、不能做什么、是否值得安装、证据来自哪里。所有项目事实必须引用 evidence_refs、source_paths 或 claim_id。\n```\n\n### 安装前体验\n\n- 目标：让用户在安装前感受核心工作流，同时避免把预览包装成真实能力或营销承诺。\n- 预期输出：一段带边界标签的体验剧本、安装后验证清单和谨慎建议；不含真实运行承诺或强营销表述。\n\n```text\n请把 cyclic-agent 当作安装前体验资产，而不是已安装工具或真实运行环境。\n\n请严格输出四段：\n1. 先问我 3 个必要问题。\n2. 给出一段“体验剧本”：用 [安装前可预览]、[必须安装后验证]、[证据不足] 三种标签展示它可能如何引导工作流。\n3. 给出安装后验证清单：列出哪些能力只有真实安装、真实宿主加载、真实项目运行后才能确认。\n4. 给出谨慎建议：只能说“值得继续研究/试装”“先补充信息后再判断”或“不建议继续”，不得替项目背书。\n\n硬性边界：\n- 不要声称已经安装、运行、执行测试、修改文件或产生真实结果。\n- 不要写“自动适配”“确保通过”“完美适配”“强烈建议安装”等承诺性表达。\n- 如果描述安装后的工作方式，必须使用“如果安装成功且宿主正确加载 Skill，它可能会……”这种条件句。\n- 体验剧本只能写成“示例台词/假设流程”：使用“可能会询问/可能会建议/可能会展示”，不要写“已写入、已生成、已通过、正在运行、正在生成”。\n- Prompt Preview 不负责给安装命令；如用户准备试装，只能提示先阅读 Quick Start 和 Risk Card，并在隔离环境验证。\n- 所有项目事实必须来自 supported claim、evidence_refs 或 source_paths；inferred/unverified 只能作风险或待确认项。\n\n```\n\n### 角色 / Skill 选择\n\n- 目标：从项目里的角色或 Skill 中挑选最匹配的资产。\n- 预期输出：候选角色或 Skill 列表，每项包含适用场景、证据路径、风险边界和是否需要安装后验证。\n\n```text\n请读取 role_skill_index，根据我的目标任务推荐 3-5 个最相关的角色或 Skill。每个推荐都要说明适用场景、可能输出、风险边界和 evidence_refs。\n```\n\n### 风险预检\n\n- 目标：安装或引入前识别环境、权限、规则冲突和质量风险。\n- 预期输出：环境、权限、依赖、许可、宿主冲突、质量风险和未知项的检查清单。\n\n```text\n请基于 risk_card、boundaries 和 quick_start_candidates，给我一份安装前风险预检清单。不要替我执行命令，只说明我应该检查什么、为什么检查、失败会有什么影响。\n```\n\n### 宿主 AI 开工指令\n\n- 目标：把项目上下文转成一次对话开始前的宿主 AI 指令。\n- 预期输出：一段边界明确、证据引用明确、适合复制给宿主 AI 的开工前指令。\n\n```text\n请基于 cyclic-agent 的 AI Context Pack，生成一段我可以粘贴给宿主 AI 的开工前指令。这段指令必须遵守 not_runtime=true，不能声称项目已经安装、运行或产生真实结果。\n```\n\n\n## 角色 / Skill 索引\n\n- 共索引 1 个角色 / Skill / 项目文档条目。\n\n- **How Does CyclicAgent Work?**（project_doc）：CyclicAgent is a framework designed for creating LLM powered, fully-autonomous AI. 激活提示：当用户需要理解项目结构、安装方式或边界时参考。 证据：`README.md`\n\n## 证据索引\n\n- 共索引 9 条证据。\n\n- **How Does CyclicAgent Work?**（documentation）：CyclicAgent is a framework designed for creating LLM powered, fully-autonomous AI. 证据：`README.md`\n- **License**（source_file）：Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files the \"Software\" , to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 证据：`LICENSE`\n- **.gitignore**（source_file）：/.env 证据：`.gitignore`\n- **Init**（source_file）：from cyclic agent.state import State from cyclic agent.executor import CyclicExecutor 证据：`cyclic_agent/__init__.py`\n- **Cot**（source_file）：class CoT State None : exit : Callable str , State llm: State prompt: str 证据：`cyclic_agent/cot.py`\n- **Executor**（source_file）：from cyclic agent.state import State 证据：`cyclic_agent/executor.py`\n- **Search**（source_file）：from typing import Callable, Annotated 证据：`cyclic_agent/search.py`\n- **def state fn: Callable A , S :**（source_file）：from future import annotations from abc import abstractmethod from pydantic import BaseModel 证据：`cyclic_agent/state.py`\n- **Pyproject**（source_file）：build-system requires = \"poetry-core\" build-backend = \"poetry.core.masonry.api\" 证据：`pyproject.toml`\n\n## 宿主 AI 必须遵守的规则\n\n- **把本资产当作开工前上下文，而不是运行环境。**：AI Context Pack 只包含证据化项目理解，不包含目标项目的可执行状态。 证据：`README.md`, `LICENSE`, `.gitignore`\n- **回答用户时区分可预览内容与必须安装后才能验证的内容。**：安装前体验的消费者价值来自降低误装和误判，而不是伪装成真实运行。 证据：`README.md`, `LICENSE`, `.gitignore`\n\n## 用户开工前应该回答的问题\n\n- 你准备在哪个宿主 AI 或本地环境中使用它？\n- 你只是想先体验工作流，还是准备真实安装？\n- 你最在意的是安装成本、输出质量、还是和现有规则的冲突？\n\n## 验收标准\n\n- 所有能力声明都能回指到 evidence_refs 中的文件路径。\n- AI_CONTEXT_PACK.md 没有把预览包装成真实运行。\n- 用户能在 3 分钟内看懂适合谁、能做什么、如何开始和风险边界。\n\n---\n\n## Doramagic Context Augmentation\n\n下面内容用于强化 Repomix/AI Context Pack 主体。Human Manual 只提供阅读骨架；踩坑日志会被转成宿主 AI 必须遵守的工作约束。\n\n## Human Manual 骨架\n\n使用规则：这里只是项目阅读路线和显著性信号，不是事实权威。具体事实仍必须回到 repo evidence / Claim Graph。\n\n宿主 AI 硬性规则：\n- 不得把页标题、章节顺序、摘要或 importance 当作项目事实证据。\n- 解释 Human Manual 骨架时，必须明确说它只是阅读路线/显著性信号。\n- 能力、安装、兼容性、运行状态和风险判断必须引用 repo evidence、source path 或 Claim Graph。\n\n- **项目介绍**：importance `high`\n  - source_paths: README.md, cyclic_agent/__init__.py\n- **安装与依赖**：importance `high`\n  - source_paths: pyproject.toml, README.md\n- **快速入门指南**：importance `high`\n  - source_paths: examples/hello_world/hello_world.py, cyclic_agent/executor.py\n- **State基类设计**：importance `high`\n  - source_paths: cyclic_agent/state.py\n- **CyclicExecutor执行器**：importance `high`\n  - source_paths: cyclic_agent/executor.py\n- **有限状态机模式**：importance `medium`\n  - source_paths: cyclic_agent/state.py, examples/bilibili_surfer/bilibili_surfer.py\n- **Search状态模块**：importance `medium`\n  - source_paths: cyclic_agent/search.py\n- **CoT状态模块**：importance `medium`\n  - source_paths: cyclic_agent/cot.py\n\n## Repo Inspection Evidence / 源码检查证据\n\n- repo_clone_verified: true\n- repo_inspection_verified: true\n- repo_commit: `40af271a355887f812da43bb45f82c35af4e2508`\n- inspected_files: `pyproject.toml`, `README.md`, `examples/hello_world/hello_world.py`, `examples/hello_world/__init__.py`, `examples/bilibili_surfer/bilibili_surfer.py`, `examples/bilibili_surfer/__init__.py`, `examples/bilibili_surfer/fifo.py`\n\n宿主 AI 硬性规则：\n- 没有 repo_clone_verified=true 时，不得声称已经读过源码。\n- 没有 repo_inspection_verified=true 时，不得把 README/docs/package 文件判断写成事实。\n- 没有 quick_start_verified=true 时，不得声称 Quick Start 已跑通。\n\n## Doramagic Pitfall Constraints / 踩坑约束\n\n这些规则来自 Doramagic 发现、验证或编译过程中的项目专属坑点。宿主 AI 必须把它们当作工作约束，而不是普通说明文字。\n\n### Constraint 1: 能力判断依赖假设\n\n- Trigger: README/documentation is current enough for a first validation pass.\n- Host AI rule: 将假设转成下游验证清单。\n- Why it matters: 假设不成立时，用户拿不到承诺的能力。\n- Evidence: capability.assumptions | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | README/documentation is current enough for a first validation pass.\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 2: 维护活跃度未知\n\n- Trigger: 未记录 last_activity_observed。\n- Host AI rule: 补 GitHub 最近 commit、release、issue/PR 响应信号。\n- Why it matters: 新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。\n- Evidence: evidence.maintainer_signals | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | last_activity_observed missing\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 3: 下游验证发现风险项\n\n- Trigger: no_demo\n- Host AI rule: 进入安全/权限治理复核队列。\n- Why it matters: 下游已经要求复核，不能在页面中弱化。\n- Evidence: downstream_validation.risk_items | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | no_demo; severity=medium\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 4: 存在评分风险\n\n- Trigger: no_demo\n- Host AI rule: 把风险写入边界卡，并确认是否需要人工复核。\n- Why it matters: 风险会影响是否适合普通用户安装。\n- Evidence: risks.scoring_risks | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | no_demo; severity=medium\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 5: issue/PR 响应质量未知\n\n- Trigger: issue_or_pr_quality=unknown。\n- Host AI rule: 抽样最近 issue/PR，判断是否长期无人处理。\n- Why it matters: 用户无法判断遇到问题后是否有人维护。\n- Evidence: evidence.maintainer_signals | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | issue_or_pr_quality=unknown\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 6: 发布节奏不明确\n\n- Trigger: release_recency=unknown。\n- Host AI rule: 确认最近 release/tag 和 README 安装命令是否一致。\n- Why it matters: 安装命令和文档可能落后于代码，用户踩坑概率升高。\n- Evidence: evidence.maintainer_signals | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | release_recency=unknown\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n",
      "summary": "给宿主 AI 的上下文和工作边界。",
      "title": "AI Context Pack / 带给我的 AI"
    },
    "boundary_risk_card": {
      "asset_id": "boundary_risk_card",
      "filename": "BOUNDARY_RISK_CARD.md",
      "markdown": "# Boundary & Risk Card / 安装前决策卡\n\n项目：xingjianll/cyclic-agent\n\n## Doramagic 试用结论\n\n当前结论：可以进入发布前推荐检查；首次使用仍应从最小权限、临时目录和可回滚配置开始。\n\n## 用户现在可以做\n\n- 可以先阅读 Human Manual，理解项目目的和主要工作流。\n- 可以复制 Prompt Preview 做安装前体验；这只验证交互感，不代表真实运行。\n- 可以把官方 Quick Start 命令放到隔离环境中验证，不要直接进主力环境。\n\n## 现在不要做\n\n- 不要把 Prompt Preview 当成项目实际运行结果。\n- 不要把 metadata-only validation 当成沙箱安装验证。\n- 不要把未验证能力写成“已支持、已跑通、可放心安装”。\n- 不要在首次试用时交出生产数据、私人文件、真实密钥或主力配置目录。\n\n## 安装前检查\n\n- 宿主 AI 是否匹配：local_cli\n- 官方安装入口状态：已发现官方入口\n- 是否在临时目录、临时宿主或容器中验证：必须是\n- 是否能回滚配置改动：必须能\n- 是否需要 API Key、网络访问、读写文件或修改宿主配置：未确认前按高风险处理\n- 是否记录了安装命令、实际输出和失败日志：必须记录\n\n## 当前阻塞项\n\n- review_required: community_discussion_evidence_below_public_threshold\n\n## 项目专属踩坑\n\n- 能力判断依赖假设（medium）：假设不成立时，用户拿不到承诺的能力。 建议检查：将假设转成下游验证清单。\n- 维护活跃度未知（medium）：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。 建议检查：补 GitHub 最近 commit、release、issue/PR 响应信号。\n- 下游验证发现风险项（medium）：下游已经要求复核，不能在页面中弱化。 建议检查：进入安全/权限治理复核队列。\n- 存在评分风险（medium）：风险会影响是否适合普通用户安装。 建议检查：把风险写入边界卡，并确认是否需要人工复核。\n- issue/PR 响应质量未知（low）：用户无法判断遇到问题后是否有人维护。 建议检查：抽样最近 issue/PR，判断是否长期无人处理。\n\n## 风险与权限提示\n\n- no_demo: medium\n\n## 证据缺口\n\n- 暂未发现结构化证据缺口。\n",
      "summary": "安装、权限、验证和推荐前风险。",
      "title": "Boundary & Risk Card / 边界与风险卡"
    },
    "human_manual": {
      "asset_id": "human_manual",
      "filename": "HUMAN_MANUAL.md",
      "markdown": "# https://github.com/xingjianll/cyclic-agent 项目说明书\n\n生成时间：2026-05-20 05:59:53 UTC\n\n## 目录\n\n- [项目介绍](#page-1)\n- [安装与依赖](#page-2)\n- [快速入门指南](#page-3)\n- [State基类设计](#page-4)\n- [CyclicExecutor执行器](#page-5)\n- [有限状态机模式](#page-6)\n- [Search状态模块](#page-7)\n- [CoT状态模块](#page-8)\n- [Hello World示例](#page-9)\n- [Bilibili Surfer示例](#page-10)\n\n<a id='page-1'></a>\n\n## 项目介绍\n\n### 相关页面\n\n相关主题：[安装与依赖](#page-2), [State基类设计](#page-4)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [README.md](https://github.com/xingjianll/cyclic-agent/blob/main/README.md)\n- [cyclic_agent/__init__.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/__init__.py)\n- [cyclic_agent/state.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/state.py)\n- [cyclic_agent/executor.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n- [cyclic_agent/search.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/search.py)\n- [cyclic_agent/cot.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/cot.py)\n- [examples/hello_world/hello_world.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/hello_world/hello_world.py)\n- [examples/bilibili_surfer/bilibili_surfer.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n- [examples/bilibili_surfer/fifo.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n</details>\n\n# 项目介绍\n\n## 1 项目概述\n\nCyclicAgent 是一个专为创建 LLM 驱动的完全自主 AI Agent 而设计的框架。该框架的核心创新在于将 Agent 抽象为有限状态机（FSM），采用状态设计模式实现。在每个状态中，Agent 根据内部状态属性（如内存、元提示等）以及外部信号来推断下一个状态，并与外部环境进行交互。\n\n资料来源：[README.md:1-10]()\n\n## 2 核心设计理念\n\n### 2.1 有限状态机架构\n\nCyclicAgent 的核心理念基于有限状态机（FSM）设计。框架中的所有状态都实现了一个状态转换函数，该函数返回另一个状态对象。这种设计允许状态转换操作无限链接，从而使 Agent 变得“循环”。\n\n```mermaid\ngraph TD\n    A[初始状态] --> B[State.next]\n    B --> C{状态转换}\n    C -->|State A| D[执行动作]\n    C -->|State B| E[执行动作]\n    D --> B\n    E --> B\n```\n\n### 2.2 状态设计模式\n\n每个状态（State）都包含一个 `next()` 方法，该方法负责确定下一个要转换到的状态。状态可以携带内部属性，如内存、提示词等，这些属性在状态转换过程中会被保留和传递。\n\n资料来源：[cyclic_agent/state.py:6-9]()\n\n## 3 核心组件\n\n### 3.1 State 基类\n\nState 是框架的基础类，定义在 `cyclic_agent/state.py` 中。所有自定义状态都必须继承此类并实现 `next()` 方法。\n\n```python\nclass State[SigT](BaseModel):\n    @abstractmethod\n    def next(self, signal: SigT | None = None) -> State[SigT]:\n        \"\"\"Transition to the next state.\"\"\"\n        raise NotImplementedError\n```\n\nState 类使用 Pydantic 的 BaseModel 作为基类，提供了数据验证和序列化能力。每个状态都有一个泛型参数 `SigT` 表示信号的接收类型，`next()` 方法接收一个可选的信号参数并返回下一个状态。\n\n资料来源：[cyclic_agent/state.py:1-10]()\n\n### 3.2 CyclicExecutor 执行器\n\nCyclicExecutor 负责执行状态机的运行循环，支持暂停、恢复和终止操作。\n\n```python\nclass CyclicExecutor:\n    def __init__(self, default_time_interval: float):\n        self.running = False\n        self.lock = threading.Lock()\n        self.default_time_interval = default_time_interval\n        self.killed = False\n        self.thread = None\n```\n\n执行器使用独立线程运行主循环，在每次状态转换后根据 `default_time_interval` 参数进行休眠，实现周期性的状态检查和转换。\n\n资料来源：[cyclic_agent/executor.py:1-33]()\n\n### 3.3 执行器控制方法\n\n| 方法 | 功能描述 | 线程安全 |\n|------|---------|----------|\n| `start(initial_state)` | 启动执行器，传入初始状态 | 是 |\n| `pause()` | 暂停执行循环 | 是 |\n| `resume()` | 恢复执行循环 | 是 |\n| `kill()` | 终止执行器 | 是 |\n\n资料来源：[cyclic_agent/executor.py:11-24]()\n\n### 3.4 预置状态组件\n\n框架提供了两个预置的状态组件用于常见场景：\n\n| 组件 | 文件位置 | 用途 |\n|------|----------|------|\n| Search | `cyclic_agent/search.py` | 执行搜索操作并根据结果转换状态 |\n| CoT | `cyclic_agent/cot.py` | 实现思维链（Chain of Thought）模式 |\n\nSearch 组件允许定义搜索查询和回调函数来根据搜索结果决定后续状态：\n\n```python\nclass Search(State[None]):\n    query: str\n    exit_: Callable[[[Annotated[str, \"search result\"]]], State]\n\n    def next(self, signal: None = None) -> State:\n        search_result = self.search(self.query)\n        return self.exit_(search_result)\n```\n\n资料来源：[cyclic_agent/search.py:1-13]()\n\nCoT 组件实现了思维链模式，通过在提示词后添加\"Let's think step by step.\"来增强 LLM 的推理能力：\n\n```python\nclass CoT(State[None]):\n    exit_: Callable[[str], State]\n    llm: State\n    prompt: str\n\n    def next(self, signal: None = None) -> State:\n        prompt = self.prompt + \"Let's think step by step.\"\n        # ... 回调处理\n```\n\n资料来源：[cyclic_agent/cot.py:1-17]()\n\n## 4 工作流程\n\n### 4.1 状态转换机制\n\nCyclicAgent 的工作流程遵循以下循环：\n\n```mermaid\ngraph LR\n    A[State 实例] -->|调用| B[next 方法]\n    B --> C[执行业务逻辑]\n    C --> D[确定下一状态]\n    D --> E[返回新状态对象]\n    E --> A\n```\n\n1. 用户创建初始状态实例\n2. 将初始状态传递给 CyclicExecutor 的 `start()` 方法\n3. 执行器在新线程中运行主循环\n4. 每次循环调用当前状态的 `next()` 方法\n5. `next()` 方法执行业务逻辑并返回下一个状态\n6. 循环回到步骤 4\n\n资料来源：[cyclic_agent/executor.py:31-35]()\n\n### 4.2 简单示例工作原理\n\n以下是一个最简单的两个状态互相转换的示例：\n\n```python\nclass AskQuestion(State[None]):\n    def next(self, signal: None = None) -> AnswerQuestion:\n        response = co.chat(message=\"Ask a question\")\n        return AnswerQuestion(question=response.text)\n\nclass AnswerQuestion(State[None]):\n    question: str\n    def next(self, signal: None = None) -> AskQuestion:\n        answer = co.chat(message=self.question)\n        return AskQuestion()\n\n# 启动执行器\nexecutor = CyclicExecutor(5)  # 5秒间隔\nexecutor.start(AskQuestion())\n```\n\n该示例创建了两个状态：AskQuestion 和 AnswerQuestion，它们互相转换形成无限循环。\n\n资料来源：[examples/hello_world/hello_world.py:1-34]()\n\n## 5 内存管理\n\n### 5.1 FIFO 队列\n\n框架通过 FIFO（先进先出）队列实现内存管理，用于记录 Agent 的历史行为和决策过程。\n\n```python\nclass Fifo:\n    def __init__(self):\n        self.capacity = 100  # 最大容量\n        self.queue = []\n        self.log_file = \"fifo_log.txt\"\n\n    def add(self, item):\n        if len(self.queue) >= self.capacity:\n            self.queue.pop(0)  # 移除最旧的记录\n        self.queue.append((item, timestamp))\n```\n\nFIFO 队列支持：\n- 容量限制：默认最大存储 100 条记录\n- 持久化日志：自动将记录写入文件\n- 时间戳记录：每条记录都附带时间戳\n- 有序检索：按时间顺序显示历史记录\n\n资料来源：[examples/bilibili_surfer/fifo.py:1-31]()\n\n### 5.2 状态继承结构\n\n在实际应用中，状态通常需要继承 `BilibiliStateBase` 等基类来获取内存和 LLM 客户端等共享资源：\n\n```python\nclass BilibiliStateBase(State[None], ABC):\n    model_config = ConfigDict(arbitrary_types_allowed=True)\n    initial_prompt: str\n    memory: Fifo\n    co: Client\n    credential: Credential\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:26-33]()\n\n## 6 包结构\n\n### 6.1 导出接口\n\n框架通过 `cyclic_agent/__init__.py` 对外导出核心接口：\n\n```python\nfrom cyclic_agent.state import State\nfrom cyclic_agent.executor import CyclicExecutor\n\n__all__ = [\"State\", \"CyclicExecutor\"]\n```\n\n用户只需导入 State 基类和 CyclicExecutor 执行器即可开始使用框架。\n\n资料来源：[cyclic_agent/__init__.py:1-6]()\n\n### 6.2 项目目录结构\n\n```\ncyclic-agent/\n├── cyclic_agent/           # 核心框架\n│   ├── __init__.py        # 包初始化，导出公共接口\n│   ├── state.py           # State 基类定义\n│   ├── executor.py        # CyclicExecutor 执行器\n│   ├── search.py          # Search 预置状态\n│   └── cot.py             # CoT 预置状态\n├── examples/              # 示例代码\n│   ├── hello_world/       # 简单示例\n│   └── bilibili_surfer/   # B站冲浪者完整示例\n└── README.md              # 项目文档\n```\n\n## 7 安装与使用\n\n### 7.1 安装方式\n\n通过 pip 安装：\n\n```shell\npip install cyclic-agent\n```\n\n资料来源：[README.md:11-13]()\n\n### 7.2 依赖要求\n\n框架使用 Pydantic 作为数据验证层，示例代码中使用了 Cohere 作为 LLM 提供商。项目依赖包括：\n\n| 依赖包 | 用途 |\n|--------|------|\n| pydantic | 数据验证和序列化 |\n| cohere | LLM 接口调用 |\n| dotenv | 环境变量管理 |\n\n资料来源：[examples/hello_world/hello_world.py:1-8]()\n\n## 8 高级特性\n\n### 8.1 状态推理助手\n\n框架提供了 `_infer_state_helper()` 方法，用于辅助 LLM 在多个可能的状态之间进行选择：\n\n```python\ndef _infer_state_helper(self, *args: str) -> str:\n    prompt = I(\n        f\"\"\"\n        {self.initial_prompt}\n        Here are your past actions {self.memory.prompt()}.\n        Here are the next states you can go to: {\", \".join(args)}\n        Give the state that you want to go to. \n        1. Give one word and nothing else.\n        2. Be creative and try different routes.\n        \"\"\"\n    )\n    text = self.co.chat(temperature=1, message=prompt).text\n    return text\n```\n\n该方法通过精心设计的提示词模板，引导 LLM 选择下一个合适的状态，同时记录历史行为以保持上下文连贯性。\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:35-50]()\n\n### 8.2 类型别名定义\n\n框架大量使用 Python 的类型别名（Type Alias）来定义可达状态集合：\n\n```python\ntype BrowsingVideoReachable = Union[BrowsingVideo, ReadingComments]\ntype ReadingCommentsReachable = Union[BrowsingVideo, ReadingComments, PostComment]\n```\n\n这种设计使得状态转换的类型提示更加清晰，也便于静态分析和代码维护。\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:51-52]()\n\n## 9 应用场景\n\n### 9.1 B站冲浪者示例\n\n一个完整的示例展示了如何使用框架创建一个自动浏览 B 站视频、阅读评论和发表评论的 Agent：\n\n```mermaid\ngraph TD\n    A[BrowsingVideo] -->|搜索视频| B[选择视频]\n    B --> C[ReadingComments]\n    C -->|查看评论| D[选择评论]\n    D --> E[PostComment]\n    E -->|发表评论| A\n    D -->|继续浏览| A\n    C -->|继续浏览| A\n```\n\n该示例实现了四个状态：\n- **BrowsingVideo**：搜索和选择要观看的视频\n- **ReadingComments**：阅读视频的热门评论\n- **PostComment**：回复选定的评论\n- 各状态之间通过 `_infer_state_helper()` 方法进行智能转换\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:55-155]()\n\n## 10 设计优势\n\n| 优势 | 说明 |\n|------|------|\n| 简洁直观 | 状态即普通的 Python 类，易于理解和实现 |\n| 类型安全 | 基于 Pydantic 的数据验证和泛型支持 |\n| 可扩展性 | 可自由定义状态数量和转换逻辑 |\n| 线程安全 | 执行器使用锁保护共享状态 |\n| 循环执行 | 支持无限循环的任务执行 |\n| 记忆能力 | 内置 FIFO 队列支持历史记录管理 |\n\nCyclicAgent 通过有限状态机模式为 LLM Agent 的构建提供了一种结构清晰、易于维护的解决方案，使开发者能够专注于业务逻辑的实现，而无需担心底层的状态管理和执行调度。\n\n---\n\n<a id='page-2'></a>\n\n## 安装与依赖\n\n### 相关页面\n\n相关主题：[项目介绍](#page-1), [快速入门指南](#page-3)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [pyproject.toml](https://github.com/xingjianll/cyclic-agent/blob/main/pyproject.toml)\n- [README.md](https://github.com/xingjianll/cyclic-agent/blob/main/README.md)\n- [cyclic_agent/__init__.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/__init__.py)\n- [cyclic_agent/state.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/state.py)\n- [cyclic_agent/executor.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n</details>\n\n# 安装与依赖\n\n## 概述\n\nCyclicAgent 是一个基于有限状态机（FSM）设计的 LLM 驱动自主代理框架。该框架采用状态设计模式，将每个代理抽象为一个状态机，通过状态之间的转换实现循环执行。资料来源：[README.md:1-5]()\n\n安装与依赖模块定义了项目的基础运行环境、核心依赖包以及可选依赖项，是用户成功部署和使用该框架的前提条件。\n\n## 环境要求\n\n### Python 版本\n\n| 要求项 | 最低版本 | 说明 |\n|--------|----------|------|\n| Python | 3.11+ | 需要支持泛型类型参数语法 `class State[SigT]` |\n\n### 核心依赖\n\nCyclicAgent 的核心功能依赖于以下 Python 包：\n\n| 依赖包 | 版本要求 | 用途 |\n|--------|----------|------|\n| pydantic | ≥2.0 | 状态基类的数据模型实现 |\n| typing_extensions | 最新版 | 支持 Python 3.11 之前的类型注解 |\n\n核心包仅包含最基础的依赖，确保框架轻量化运行。资料来源：[cyclic_agent/state.py:1-6]()\n\n## 安装方式\n\n### 使用 pip 安装\n\nCyclicAgent 可通过 Python 包管理器 pip 直接安装：\n\n```shell\npip install cyclic-agent\n```\n\n该命令会自动安装所有核心依赖。资料来源：[README.md:8-10]()\n\n### 从源码安装\n\n对于开发者或需要修改源码的用户，可通过 GitHub 仓库克隆并安装：\n\n```shell\ngit clone https://github.com/xingjianll/cyclic-agent.git\ncd cyclic-agent\npip install -e .\n```\n\n## 核心模块依赖\n\n### 模块架构\n\n```mermaid\ngraph TD\n    A[cyclic_agent] --> B[state.py]\n    A --> C[executor.py]\n    A --> D[__init__.py]\n    \n    B --> E[pydantic.BaseModel]\n    C --> F[threading]\n    C --> G[time]\n    \n    style A fill:#e1f5fe\n    style B fill:#f3e5f5\n    style C fill:#fff3e0\n```\n\n### 状态基类依赖\n\n`State` 是框架的核心抽象类，继承自 `pydantic.BaseModel`，提供了状态机的数据验证和序列化能力。资料来源：[cyclic_agent/state.py:5]()\n\n```python\nfrom pydantic import BaseModel\n\nclass State[SigT](BaseModel):\n    @abstractmethod\n    def next(self, signal: SigT | None = None) -> State[SigT]:\n        \"\"\"转换到下一个状态\"\"\"\n        raise NotImplementedError\n```\n\n### 执行器依赖\n\n`CyclicExecutor` 负责管理状态机的生命周期，使用标准库的线程机制实现后台运行。资料来源：[cyclic_agent/executor.py:1-7]()\n\n| 模块 | 来源 | 用途 |\n|------|------|------|\n| threading | 标准库 | 多线程状态循环执行 |\n| time | 标准库 | 执行间隔控制 |\n\n## 可选依赖\n\n根据具体应用场景，用户可能需要安装以下可选依赖：\n\n### LLM 提供商\n\n| 包名 | 说明 | 用途示例 |\n|------|------|----------|\n| cohere | Cohere API 客户端 | 实现与 Cohere LLM 的交互 |\n\n安装可选 LLM 依赖：\n\n```shell\npip install cohere\n```\n\n### 环境变量管理\n\n| 包名 | 说明 |\n|------|------|\n| python-dotenv | 从 `.env` 文件加载环境变量 |\n\n### 第三方集成\n\n复杂示例（如 Bilibili 冲浪者）可能需要额外依赖：\n\n| 包名 | 用途 |\n|------|------|\n| bilibili-api-python | Bilibili API 封装 |\n| overrides | 方法重写装饰器 |\n\n## 环境变量配置\n\n### 必需的环境变量\n\n在使用 LLM 提供商时，需要配置相应的 API 密钥：\n\n```python\nimport os\nfrom dotenv import load_dotenv\n\nload_dotenv()  # 从 .env 文件加载环境变量\n\nco = cohere.Client(os.environ.get(\"COHERE_API_KEY\"))\n```\n\n### .env 文件示例\n\n```\nCOHERE_API_KEY=your_api_key_here\n```\n\n资料来源：[examples/hello_world/hello_world.py:1-11]()\n\n## 包导出结构\n\n框架通过 `__init__.py` 向外暴露核心接口：资料来源：[cyclic_agent/__init__.py:1-5]()\n\n```mermaid\ngraph LR\n    A[cyclic_agent] --> B[State]\n    A --> C[CyclicExecutor]\n    \n    B --> D[状态基类]\n    C --> E[执行器]\n```\n\n| 导出项 | 模块路径 | 说明 |\n|--------|----------|------|\n| `State` | cyclic_agent.state | 状态机抽象基类 |\n| `CyclicExecutor` | cyclic_agent.executor | 状态循环执行器 |\n\n## 安装验证\n\n安装完成后，可通过以下方式验证：\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\n\n# 验证导入成功\nprint(\"CyclicAgent 安装成功\")\n```\n\n## 依赖冲突处理\n\n### 类型注解兼容\n\n框架使用 Python 3.11+ 的新语法 `class State[SigT]`，如果使用旧版本 Python 可能需要以下导入：\n\n```python\nfrom __future__ import annotations\n```\n\n此导入使类型注解使用字符串延迟求值，确保与旧版本兼容。资料来源：[examples/hello_world/hello_world.py:1]()\n\n### Pydantic 版本\n\n框架使用 Pydantic v2 的配置方式：\n\n```python\nfrom pydantic import ConfigDict\n\nclass BilibiliStateBase(State[None]):\n    model_config = ConfigDict(arbitrary_types_allowed=True)\n```\n\n如使用 Pydantic v1，需要调整配置方式。\n\n## 快速开始依赖清单\n\n完整的快速开始示例所需依赖：\n\n| 依赖包 | 安装命令 | 用途 |\n|--------|----------|------|\n| cyclic-agent | `pip install cyclic-agent` | 核心框架 |\n| cohere | `pip install cohere` | LLM 调用 |\n| python-dotenv | `pip install python-dotenv` | 环境变量 |\n\n## 常见问题\n\n### Q: 是否需要安装可选依赖？\n\nA: 核心功能仅需安装 `cyclic-agent` 即可运行。可选依赖根据具体使用场景决定是否安装。\n\n### Q: 如何确认安装成功？\n\nA: 执行 `python -c \"from cyclic_agent import State, CyclicExecutor\"` 无报错即表示安装成功。\n\n### Q: 框架支持哪些 Python 版本？\n\nA: 推荐使用 Python 3.11+，以获得完整的类型注解支持。\n\n---\n\n<a id='page-3'></a>\n\n## 快速入门指南\n\n### 相关页面\n\n相关主题：[安装与依赖](#page-2), [State基类设计](#page-4), [Bilibili Surfer示例](#page-10)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [examples/hello_world/hello_world.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/hello_world/hello_world.py)\n- [cyclic_agent/executor.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n- [cyclic_agent/state.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/state.py)\n- [cyclic_agent/cot.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/cot.py)\n- [cyclic_agent/search.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/search.py)\n- [examples/bilibili_surfer/bilibili_surfer.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n- [examples/bilibili_surfer/fifo.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n</details>\n\n# 快速入门指南\n\n## 概述\n\nCyclicAgent 是一个基于有限状态机（FSM）设计的 LLM 驱动自主 AI Agent 框架。该框架采用状态设计模式，将每个 Agent 抽象为有限状态机，通过状态之间的转换实现 Agent 的循环执行能力。资料来源：[README.md:1-5]()\n\n## 核心概念\n\n### 状态（State）\n\n状态是 CyclicAgent 框架的基础单元。每个状态都继承自 `State` 基类，并实现 `next()` 方法来决定状态转换逻辑。资料来源：[cyclic_agent/state.py:7-10]()\n\n```python\nclass State[SigT](BaseModel):\n    @abstractmethod\n    def next(self, signal: SigT | None = None) -> State[SigT]:\n        \"\"\"Transition to the next state.\"\"\"\n        raise NotImplementedError\n```\n\n### 循环执行器（CyclicExecutor）\n\n`CyclicExecutor` 负责管理状态机的执行循环，通过独立的线程持续调用状态的 `next()` 方法来实现状态转换。资料来源：[cyclic_agent/executor.py:8-11]()\n\n```python\nclass CyclicExecutor:\n    def __init__(self, default_time_interval: float):\n        self.running = False\n        self.lock = threading.Lock()\n        self.default_time_interval = default_time_interval\n```\n\n## 工作原理\n\nCyclicAgent 的核心工作原理是将 Agent 抽象为有限状态机。在每个状态下，Agent 根据内部状态属性（如 memory、meta prompts）以及外部信号推断下一个状态，并与外部环境进行交互。所有状态都实现状态转换函数，返回另一个状态，从而实现状态的无限链接，使 Agent 具备\"循环\"特性。资料来源：[README.md:10-15]()\n\n```mermaid\ngraph TD\n    A[初始状态] --> B{State.next}\n    B -->|返回新状态| C[下一状态]\n    C --> B\n    B -->|接收外部信号| D[信号处理]\n    D --> C\n```\n\n## 安装与配置\n\n### 环境要求\n\n| 要求项 | 说明 |\n|--------|------|\n| Python 版本 | 3.8+ |\n| 核心依赖 | Pydantic |\n| LLM 提供商 | Cohere（示例使用） |\n| 环境管理 | dotenv |\n\n### 安装方式\n\n```shell\npip install cyclic-agent\n```\n\n### 环境变量配置\n\n创建 `.env` 文件并配置必要的 API 密钥：\n\n```bash\nCOHERE_API_KEY=your_cohere_api_key\n```\n\n## 快速开始\n\n### 环境准备\n\n1. 安装 cyclic-agent 包\n2. 配置环境变量或使用 `load_dotenv()` 加载 `.env` 文件\n3. 导入必要的模块：\n\n```python\nfrom __future__ import annotations\nfrom cyclic_agent import State, CyclicExecutor\n```\n\n### 基础示例：问答循环\n\n以下示例创建了一个简单的问答 Agent，包含两个相互转换的状态。资料来源：[examples/hello_world/hello_world.py:1-40]()\n\n```python\nfrom __future__ import annotations\nimport os\nimport time\n\nimport cohere\nfrom dotenv import load_dotenv\n\nfrom cyclic_agent import State, CyclicExecutor\n\nload_dotenv()\nco = cohere.Client(os.environ.get(\"COHERE_API_KEY\"))\n\n\nclass AskQuestion(State[None]):\n    def next(self, signal: None = None) -> AnswerQuestion:\n        response = co.chat(message=\"Ask a question\", temperature=1)\n        print(response.text)\n        return AnswerQuestion(question=response.text)\n\n\nclass AnswerQuestion(State[None]):\n    question: str\n\n    def next(self, signal: None = None) -> AskQuestion:\n        answer = co.chat(message=self.question)\n        print(answer)\n        return AskQuestion()\n\n\nif __name__ == \"__main__\":\n    initial_state = AskQuestion()\n    executor = CyclicExecutor(5)\n    executor.start(initial_state)\n    time.sleep(20)\n```\n\n### 状态转换流程\n\n```mermaid\ngraph LR\n    A[AskQuestion] -->|next()| B[AnswerQuestion]\n    B -->|next()| A\n    style A fill:#e1f5fe\n    style B fill:#fff3e0\n```\n\n## 进阶示例：B站冲浪 Agent\n\n以下示例展示了更复杂的状态机实现，包含浏览视频、阅读评论、发表评论等多个状态。资料来源：[examples/bilibili_surfer/bilibili_surfer.py:1-180]()\n\n### 状态结构\n\n| 状态类 | 功能 | 可转换状态 |\n|--------|------|------------|\n| `BrowsingVideo` | 搜索和浏览视频 | `BrowsingVideo`, `ReadingComments` |\n| `ReadingComments` | 读取视频评论 | `BrowsingVideo`, `ReadingComments`, `PostComment` |\n| `PostComment` | 发表/回复评论 | `BrowsingVideo` |\n\n### 状态基类设计\n\n所有 Bilibili 相关状态继承自 `BilibiliStateBase`，该基类封装了通用逻辑。资料来源：[examples/bilibili_surfer/bilibili_surfer.py:27-52]()\n\n```python\nclass BilibiliStateBase(State[None], ABC):\n    model_config = ConfigDict(arbitrary_types_allowed=True)\n    initial_prompt: str\n    memory: Fifo\n    co: Client\n    credential: Credential\n\n    def _infer_state_helper(self, *args: str) -> str:\n        prompt = I(\n            f\"\"\"\n            {self.initial_prompt}\n            Here are your past actions {self.memory.prompt()}.\n            Here are the next states you can go to: {\", \".join(args)}\n            Give the state that you want to go to. \n            1. Give one word and nothing else.\n            2. Be creative and try different routes.\n            \"\"\"\n        )\n        text = self.co.chat(temperature=1, message=prompt).text\n        return text\n```\n\n### 内存管理\n\n使用 FIFO 队列记录 Agent 的历史行为，辅助 LLM 做决策。资料来源：[examples/bilibili_surfer/fifo.py:1-30]()\n\n```python\nclass Fifo:\n    def __init__(self):\n        self.capacity = 100\n        self.queue = []\n        self.log_file = \"fifo_log.txt\"\n\n    def add(self, item):\n        if len(self.queue) >= self.capacity:\n            self.queue.pop(0)\n        timestamp = datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n        self.queue.append((item, timestamp))\n        self.log_to_file(item, timestamp)\n\n    def prompt(self):\n        return \"\\n\".join([f\"{time} - {text}\" for text, time in reversed(self.queue)])\n```\n\n### 完整状态转换图\n\n```mermaid\ngraph TD\n    A[BrowsingVideo] -->|搜索视频| B{状态选择}\n    B -->|BrowsingVideo| A\n    B -->|ReadingComments| C[ReadingComments]\n    C -->|读取评论| D{状态选择}\n    D -->|BrowsingVideo| A\n    D -->|ReadingComments| C\n    D -->|PostComment| E[PostComment]\n    E -->|发表评论| A\n    style A fill:#e1f5fe\n    style C fill:#e8f5e9\n    style E fill:#fff3e0\n```\n\n## 状态机类型定义\n\n框架使用 Python 类型别名定义状态转换规则。资料来源：[examples/bilibili_surfer/bilibili_surfer.py:54-55]()\n\n```python\ntype BrowsingVideoReachable = Union[BrowsingVideo, ReadingComments]\ntype ReadingCommentsReachable = Union[BrowsingVideo, ReadingComments, PostComment]\ntype PostCommentReachable = Union[BrowsingVideo]\n```\n\n## 执行器控制\n\n`CyclicExecutor` 提供以下控制方法：\n\n| 方法 | 功能 | 线程安全 |\n|------|------|----------|\n| `start(initial_state)` | 启动状态机 | 是 |\n| `pause()` | 暂停执行 | 是 |\n| `resume()` | 恢复执行 | 是 |\n| `kill()` | 停止并清理 | 是 |\n\n资料来源：[cyclic_agent/executor.py:13-31]()\n\n## 内置组件\n\n### 思维链（CoT）\n\n`CoT` 组件支持思维链推理模式。资料来源：[cyclic_agent/cot.py:1-20]()\n\n```python\nclass CoT(State[None]):\n    exit_: Callable[[str], State]\n    llm: State\n    prompt: str\n\n    def next(self, signal: None = None) -> State:\n        prompt = self.prompt + \"Let's think step by step.\"\n        def callback(answer: str) -> State:\n            return self.exit_(answer)\n        return self.llm(prompt=prompt, callback=callback)\n```\n\n### 搜索组件（Search）\n\n`Search` 组件提供搜索功能抽象。资料来源：[cyclic_agent/search.py:1-18]()\n\n```python\nclass Search(State[None]):\n    query: str\n    exit_: Callable[[[Annotated[str, \"search result\"]]], State]\n\n    def next(self, signal: None = None) -> State:\n        search_result = self.search(self.query)\n        return self.exit_(search_result)\n\n    def search(self, query: str) -> str:\n        raise NotImplementedError\n```\n\n## 最佳实践\n\n### 前向引用注意事项\n\n由于状态类之间存在循环引用，必须使用 `from __future__ import annotations` 启用前向引用支持。资料来源：[examples/hello_world/hello_world.py:3]()\n\n```python\nfrom __future__ import annotations\n```\n\n### 模型_dump() 的使用\n\n在状态转换时使用 Pydantic 的 `model_dump()` 方法传递状态数据。资料来源：[examples/bilibili_surfer/bilibili_surfer.py:71-73]()\n\n```python\nreturn BrowsingVideo(**self.model_dump(exclude={'video_bvid', 'video_title', 'video_description'}))\n```\n\n### 异步操作处理\n\n使用 `asyncio.run()` 在同步状态方法中处理异步 API 调用。资料来源：[examples/bilibili_surfer/bilibili_surfer.py:87-90]()\n\n```python\nresponse = asyncio.run(comment.send_comment(\n    text=f\"{response} {footnote}\",\n    oid=video.Video(bvid=self.video_bvid).get_aid(),\n    type_=CommentResourceType.VIDEO,\n    credential=self.credential\n))\n```\n\n### LLM 决策引导\n\n通过结构化的 prompt 引导 LLM 做出符合预期的状态选择决策。资料来源：[examples/bilibili_surfer/bilibili_surfer.py:35-48]()\n\n```python\nprompt = I(\n    f\"\"\"\n    {self.initial_prompt}\n    Here are your past actions {self.memory.prompt()}.\n    Here are the next states you can go to: {\", \".join(args)}\n    Give the state that you want to go to. \n    1. Give one word and nothing else.\n    2. Be creative and try different routes.\n    \"\"\"\n)\n```\n\n## 下一步\n\n- 深入阅读 [核心组件文档](./core-components.md) 了解更多内置组件\n- 查看 [示例项目](./examples.md) 获取更多实践参考\n- 探索 [高级用法](./advanced-usage.md) 学习自定义状态转换逻辑\n\n---\n\n<a id='page-4'></a>\n\n## State基类设计\n\n### 相关页面\n\n相关主题：[CyclicExecutor执行器](#page-5), [有限状态机模式](#page-6)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [cyclic_agent/state.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/state.py)\n- [cyclic_agent/executor.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n- [cyclic_agent/__init__.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/__init__.py)\n- [cyclic_agent/search.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/search.py)\n- [cyclic_agent/cot.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/cot.py)\n- [examples/hello_world/hello_world.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/hello_world/hello_world.py)\n- [examples/bilibili_surfer/bilibili_surfer.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n</details>\n\n# State基类设计\n\n## 概述\n\nCyclicAgent框架的核心设计基于**有限状态机（FSM）**概念，通过状态设计模式将AI Agent抽象为可循环执行的状态机。`State`基类是整个框架的基础抽象，定义了状态转换的标准接口。\n\n状态机的工作原理是：每个状态实现一个`next()`方法，该方法根据内部状态属性（如memory、meta prompts等）和外部信号推断下一个状态，并返回另一个状态对象。这种设计使得状态转换操作可以无限链式执行，从而实现Agent的\"循环\"特性。\n\n## 核心架构\n\n### 状态转换流程\n\n```mermaid\ngraph TD\n    A[State开始] --> B{执行next方法}\n    B --> C[根据业务逻辑确定下一状态]\n    C --> D[返回新状态对象]\n    D --> E{CyclicExecutor是否继续?}\n    E -->|是| B\n    E -->|否| F[结束]\n    \n    G[外部信号] -.-> B\n    H[内部状态属性] -.-> B\n```\n\n### 状态与执行器的关系\n\n```mermaid\ngraph LR\n    A[CyclicExecutor] -->|持有当前状态| B[State实例]\n    B -->|调用next返回| C[下一State]\n    C -->|循环| B\n    D[Thread] -->|运行主循环| A\n```\n\n## State基类规范\n\n### 基类定义\n\n```python\nclass State[SigT](BaseModel):\n    @abstractmethod\n    def next(self, signal: SigT | None = None) -> State[SigT]:\n        \"\"\"Transition to the next state.\"\"\"\n        raise NotImplementedError\n```\n\n资料来源：[cyclic_agent/state.py:6-10]()\n\n### 关键特性\n\n| 特性 | 说明 |\n|------|------|\n| 泛型设计 | 使用Python泛型`[SigT]`定义信号类型参数 |\n| Pydantic集成 | 继承`BaseModel`，支持数据验证和序列化 |\n| 抽象方法 | `next()`必须由子类实现 |\n| 信号机制 | 支持可选的外部信号参数 |\n\n### 类型参数说明\n\n| 参数 | 含义 | 用途 |\n|------|------|------|\n| `SigT` | Signal Type | 定义状态间传递的信号数据类型 |\n| `State[None]` | 无信号状态 | 状态间无需传递数据，如`AskQuestion` |\n| `State[str]` | 字符串信号 | 可携带文本信息进行状态转换 |\n\n## 执行器设计\n\n### CyclicExecutor类\n\n`CyclicExecutor`负责在独立线程中运行状态机的主循环，通过`time.sleep()`控制状态转换的时间间隔。\n\n```python\nclass CyclicExecutor:\n    def __init__(self, default_time_interval: float):\n        self.running = False\n        self.lock = threading.Lock()\n        self.default_time_interval = default_time_interval\n        self.killed = False\n        self.thread = None\n```\n\n资料来源：[cyclic_agent/executor.py:1-7]()\n\n### 执行器控制方法\n\n| 方法 | 功能 | 线程安全性 |\n|------|------|------------|\n| `start(initial_state)` | 启动执行线程 | 线程安全 |\n| `pause()` | 暂停状态机 | 线程安全 |\n| `resume()` | 恢复执行 | 线程安全 |\n| `kill()` | 终止执行 | 线程安全 |\n\n### 主循环实现\n\n```python\ndef _main_loop(self, state: State) -> None:\n    while True:\n        if self.killed:\n            return\n        if self.running:\n            state = state.next()\n            time.sleep(self.default_time_interval)\n```\n\n资料来源：[cyclic_agent/executor.py:30-36]()\n\n## 状态实现模式\n\n### 简单状态示例\n\n最简单的状态实现只需继承`State[None]`，当状态不需要传递数据时：\n\n```python\nclass AskQuestion(State[None]):\n    def next(self, signal: None = None) -> AnswerQuestion:\n        response = co.chat(message=\"Ask a question\", temperature=1)\n        return AnswerQuestion(question=response.text)\n```\n\n资料来源：[examples/hello_world/hello_world.py:14-18]()\n\n### 带状态属性的状态\n\n通过Pydantic的字段定义，状态可以持有任意业务数据：\n\n```python\nclass AnswerQuestion(State[None]):\n    question: str  # 状态属性：保存问题内容\n    \n    def next(self, signal: None = None) -> AskQuestion:\n        answer = co.chat(message=self.question)\n        return AskQuestion()\n```\n\n资料来源：[examples/hello_world/hello_world.py:20-25]()\n\n### 复杂状态基类\n\n实际应用中，状态通常需要共享资源。框架通过继承模式实现：\n\n```python\nclass BilibiliStateBase(State[None], ABC):\n    model_config = ConfigDict(arbitrary_types_allowed=True)\n    initial_prompt: str\n    memory: Fifo\n    co: Client\n    credential: Credential\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:27-32]()\n\n### 类型别名定义可到达状态\n\n```python\ntype BrowsingVideoReachable = Union[BrowsingVideo, ReadingComments]\n\nclass BrowsingVideo(BilibiliStateBase):\n    @overrides\n    def next(self, signal: None = None) -> BrowsingVideoReachable:\n        ...\n        match self._infer_state_helper('BrowsingVideo', 'ReadingComments'):\n            case 'BrowsingVideo':\n                return self\n            case 'ReadingComments':\n                return ReadingComments(...)\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:72-89]()\n\n## 状态转换模式\n\n### 一对一转换\n\n最基础的转换模式：每个状态明确返回下一个状态类型：\n\n```mermaid\ngraph LR\n    A[AskQuestion] -->|返回AnswerQuestion| B[AnswerQuestion]\n    B -->|返回AskQuestion| A\n```\n\n### 多分支转换\n\n通过类型联合和模式匹配实现条件转换：\n\n```python\ntype ReadingCommentsReachable = Union[BrowsingVideo, ReadingComments, PostComment]\n\ndef next(self, signal: None = None) -> ReadingCommentsReachable:\n    ...\n    match self._infer_state_helper('BrowsingVideo', 'ReadingComments', 'PostComment'):\n        case 'BrowsingVideo':\n            return BrowsingVideo(...)\n        case 'ReadingComments':\n            return self\n        case 'PostComment':\n            return PostComment(...)\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:116-129]()\n\n### 自引用转换\n\n状态可以返回自身保持不变：\n\n```python\ncase 'BrowsingVideo':\n    return self  # 保持当前状态\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:118]()\n\n## 内置状态组件\n\n### Search状态\n\n框架提供了可扩展的`Search`状态基类：\n\n```python\nclass Search(State[None]):\n    query: str\n    exit_: Callable[[[Annotated[str, \"search result\"]]], State]\n    \n    def next(self, signal: None = None) -> State:\n        search_result = self.search(self.query)\n        return self.exit_(search_result)\n    \n    def search(self, query: str) -> str:\n        raise NotImplementedError\n```\n\n资料来源：[cyclic_agent/search.py:1-12]()\n\n### Chain of Thought状态\n\n```python\nclass CoT(State[None]):\n    exit_: Callable[[str], State]\n    llm: State\n    prompt: str\n    \n    def next(self, signal: None = None) -> State:\n        prompt = self.prompt + \"Let's think step by step.\"\n        def callback(answer: str) -> State:\n            return self.exit_(answer)\n        return self.llm(prompt=prompt, callback=callback)\n```\n\n资料来源：[cyclic_agent/cot.py:1-16]()\n\n## 包导出结构\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\n\n__all__ = [\"State\", \"CyclicExecutor\"]\n```\n\n资料来源：[cyclic_agent/__init__.py:1-6]()\n\n## 使用流程\n\n```mermaid\ngraph TD\n    A[定义State子类] --> B[实现next方法]\n    B --> C[创建初始状态实例]\n    C --> D[创建CyclicExecutor]\n    D --> E[调用start方法]\n    E --> F[线程运行主循环]\n    F --> G[状态无限转换]\n    G --> H[外部调用kill终止]\n```\n\n## 设计优势\n\n| 优势 | 说明 |\n|------|------|\n| 简洁性 | 单一抽象方法`next()`定义状态行为 |\n| 灵活性 | Pydantic提供强大的数据验证 |\n| 可扩展性 | 继承基类即可创建新状态类型 |\n| 类型安全 | 泛型设计支持类型检查 |\n| 可测试性 | 每个状态独立，易于单元测试 |\n\n## 最佳实践\n\n### 1. 前向引用声明\n\n使用状态类型时需要前向引用：\n\n```python\nfrom __future__ import annotations\n\nclass AskQuestion(State[None]):\n    def next(self, signal: None = None) -> AnswerQuestion:\n        ...\n```\n\n资料来源：[examples/hello_world/hello_world.py:1-2]()\n\n### 2. 使用`@overrides`装饰器\n\n明确标注方法重写：\n\n```python\nfrom overrides import overrides\n\nclass BrowsingVideo(BilibiliStateBase):\n    @overrides\n    def next(self, signal: None = None) -> BrowsingVideoReachable:\n        ...\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:69-72]()\n\n### 3. 状态继承层次\n\n复杂应用建议使用多层继承：\n\n```mermaid\ngraph TD\n    A[State基类] --> B[业务状态基类]\n    B --> C[BrowsingVideo]\n    B --> D[ReadingComments]\n    B --> E[PostComment]\n```\n\n### 4. 内存管理\n\n使用`model_dump()`传递状态属性：\n\n```python\nreturn BrowsingVideo(**self.model_dump(exclude={'video_bvid', 'video_title', 'video_description'}))\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:83-85]()\n\n---\n\n<a id='page-5'></a>\n\n## CyclicExecutor执行器\n\n### 相关页面\n\n相关主题：[State基类设计](#page-4), [快速入门指南](#page-3)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [cyclic_agent/executor.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n- [cyclic_agent/state.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/state.py)\n- [cyclic_agent/__init__.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/__init__.py)\n- [examples/hello_world/hello_world.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/hello_world/hello_world.py)\n- [examples/bilibili_surfer/bilibili_surfer.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n- [examples/bilibili_surfer/fifo.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n</details>\n\n# CyclicExecutor执行器\n\n## 概述\n\nCyclicExecutor是CyclicAgent框架的核心执行引擎，负责驱动基于有限状态机（FSM）的自主代理运行。该执行器通过多线程机制和状态转换循环，使AI代理能够在各个状态之间持续流转，从而实现完全自主的AI行为。\n\nCyclicExecutor的设计遵循状态设计模式，将每个代理抽象为一个有限状态机，其中每个状态都包含一个`next()`方法，该方法根据内部状态属性（如内存、元提示等）以及外部信号推断下一个状态，并返回另一个状态对象。这种设计使得状态转换操作可以无限链接，从而形成\"循环\"的代理行为。\n\n资料来源：[cyclic_agent/executor.py:1-44](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n\n## 核心架构\n\n### 组件关系\n\nCyclicExecutor与State基类之间的关系构成了框架的核心架构。State类作为所有状态节点的抽象基类，定义了状态转换的接口规范；CyclicExecutor则负责按照设定的节奏驱动状态机持续运行。\n\n```mermaid\ngraph TD\n    A[CyclicExecutor] -->|管理| B[State 状态节点]\n    B -->|返回| B\n    A -->|启动线程| C[_main_loop 主循环]\n    C -->|循环调用| D[state.next]\n    D -->|状态转换| B\n```\n\n### 类结构\n\n| 类名 | 文件位置 | 职责 |\n|------|----------|------|\n| CyclicExecutor | cyclic_agent/executor.py | 状态机执行引擎 |\n| State | cyclic_agent/state.py | 状态抽象基类 |\n| Timer | cyclic_agent/executor.py | 占位类（未实现） |\n\n资料来源：[cyclic_agent/executor.py:1-44](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)，[cyclic_agent/state.py:1-20](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/state.py)\n\n## CyclicExecutor类详解\n\n### 类定义与初始化\n\n```python\nclass CyclicExecutor:\n    def __init__(self, default_time_interval: float):\n        self.running = False\n        self.lock = threading.Lock()\n        self.default_time_interval = default_time_interval\n        self.killed = False\n        self.thread = None\n```\n\nCyclicExecutor在初始化时接受一个`default_time_interval`参数，该参数指定状态转换之间的默认时间间隔（秒）。初始化后，执行器处于停止状态，需要通过`start()`方法启动。\n\n资料来源：[cyclic_agent/executor.py:8-14](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n\n### 生命周期控制方法\n\nCyclicExecutor提供了完整的生命周期控制接口，支持启动、暂停、恢复和终止操作：\n\n| 方法 | 功能 | 线程安全 |\n|------|------|----------|\n| start(initial_state) | 启动执行器，创建新线程运行主循环 | 否（仅首次调用有效） |\n| pause() | 暂停状态机执行 | 是（使用Lock） |\n| resume() | 恢复状态机执行 | 是（使用Lock） |\n| kill() | 彻底终止执行器 | 是（使用Lock） |\n\n```python\ndef start(self, initial_state: State) -> None:\n    if not self.running:\n        self.running = True\n        self.thread = threading.Thread(target=self._main_loop, args=(initial_state,))\n        self.thread.start()\n```\n\n`start()`方法检查执行器是否已在运行，若否则创建新的后台线程并启动主循环。初始状态作为参数传入，该状态将成为状态机的第一个活跃节点。\n\n```python\ndef kill(self):\n    with self.lock:\n        self.killed = True\n        self.running = False\n    if self.thread:\n        self.thread.join()\n```\n\n`kill()`方法通过设置`killed`标志并调用线程的`join()`方法确保线程完全终止，实现执行器的优雅关闭。\n\n资料来源：[cyclic_agent/executor.py:16-39](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n\n### 主循环机制\n\n主循环是CyclicExecutor的核心，它在独立线程中持续运行，不断调用当前状态的`next()`方法并接收返回的下一个状态：\n\n```python\ndef _main_loop(self, state: State) -> None:\n    while True:\n        if self.killed:\n            return\n\n        if self.running:\n            state = state.next()\n            time.sleep(self.default_time_interval)\n```\n\n主循环的工作流程如下：首先检查`killed`标志，若为真则直接返回退出循环；然后检查`running`标志，在执行器处于运行状态时，调用当前状态的`next()`方法获取下一个状态对象，并用返回值更新当前状态引用；最后按照`default_time_interval`设定的时间间隔休眠。\n\n```mermaid\ngraph TD\n    A[开始循环] --> B{killed == True?}\n    B -->|是| Z[退出循环]\n    B -->|否| C{running == True?}\n    C -->|否| A\n    C -->|是| D[调用 state.next]\n    D --> E[获取下一状态]\n    E --> F[更新 state 引用]\n    F --> G[休眠 default_time_interval]\n    G --> A\n```\n\n资料来源：[cyclic_agent/executor.py:41-48](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n\n## State基类\n\nState是所有状态节点的抽象基类，基于Pydantic的BaseModel实现，支持类型提示和自动验证：\n\n```python\nclass State[SigT](BaseModel):\n    @abstractmethod\n    def next(self, signal: SigT | None = None) -> State[SigT]:\n        \"\"\"Transition to the next state.\"\"\"\n        raise NotImplementedError\n```\n\nState类使用Python 3.12引入的泛型参数`SigT`来指定信号的泛型类型。`next()`方法是抽象方法，要求所有子类必须实现，用于定义状态转换逻辑并返回下一个状态对象。\n\n状态转换的核心约定是：每个状态的`next()`方法返回另一个State对象，这个返回的状态将成为下一个循环迭代的当前状态。这种设计使得状态转换形成了一个可以无限持续的循环。\n\n资料来源：[cyclic_agent/state.py:1-20](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/state.py)\n\n## 使用模式与示例\n\n### 基础问答模式\n\n最简单的应用场景是两个状态之间来回切换，实现自动问答功能：\n\n```python\nclass AskQuestion(State[None]):\n    def next(self, signal: None = None) -> AnswerQuestion:\n        response = co.chat(message=\"Ask a question\", temperature=1)\n        print(response.text)\n        return AnswerQuestion(question=response.text)\n\nclass AnswerQuestion(State[None]):\n    question: str\n\n    def next(self, signal: None = None) -> AskQuestion:\n        answer = co.chat(message=self.question)\n        print(answer)\n        return AskQuestion()\n\nif __name__ == \"__main__\":\n    initial_state = AskQuestion()\n    executor = CyclicExecutor(5)\n    executor.start(initial_state)\n```\n\n该示例创建了两个状态：AskQuestion向大模型提问，AnswerQuestion接收问题并回答。两个状态相互返回对方，形成无限循环的执行流。执行器设置5秒间隔，控制状态转换的频率。\n\n资料来源：[examples/hello_world/hello_world.py:1-38](https://github.com/xingjianll/cyclic-agent/blob/main/examples/hello_world/hello_world.py)\n\n### 复杂多状态模式\n\nBilibili冲浪者示例展示了更复杂的应用，包含浏览视频、阅读评论和发表评论三个主要状态：\n\n```python\nclass BrowsingVideo(BilibiliStateBase):\n    @overrides\n    def next(self, signal: None = None) -> BrowsingVideoReachable:\n        # 搜索视频、选择视频\n        # 根据LLM决策返回下一状态\n        match self._infer_state_helper('BrowsingVideo', 'ReadingComments'):\n            case 'BrowsingVideo':\n                return self\n            case 'ReadingComments':\n                return ReadingComments(**self.model_dump(), ...)\n\nclass ReadingComments(BilibiliStateBase):\n    @overrides\n    def next(self, signal: None = None) -> ReadingCommentsReachable:\n        # 获取评论、选择评论\n        match self._infer_state_helper('BrowsingVideo', 'ReadingComments', 'PostComment'):\n            case 'BrowsingVideo':\n                return BrowsingVideo(...)\n            case 'ReadingComments':\n                return self\n            case 'PostComment':\n                return PostComment(...)\n\nclass PostComment(BilibiliStateBase):\n    @overrides\n    def next(self, signal: None = None) -> PostCommentReachable:\n        # 发表评论、发布动态\n        return BrowsingVideo(...)\n```\n\n状态之间通过类型别名（Type Alias）定义可达关系，增强了类型安全性和代码可读性：\n\n```python\ntype BrowsingVideoReachable = Union[BrowsingVideo, ReadingComments]\ntype ReadingCommentsReachable = Union[BrowsingVideo, ReadingComments, PostComment]\ntype PostCommentReachable = Union[BrowsingVideo]\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:1-180](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n\n### 状态转换流程图\n\n```mermaid\ngraph LR\n    A[BrowsingVideo<br/>浏览视频] -->|阅读评论| B[ReadingComments<br/>阅读评论]\n    B -->|继续浏览| A\n    B -->|发表评论| C[PostComment<br/>发表评论]\n    C -->|完成| A\n    A -->|继续浏览| A\n```\n\n### 内存与记忆机制\n\n复杂代理通常需要维护内存以追踪历史行为。示例中的Fifo类实现了先入先出队列：\n\n```python\nclass Fifo:\n    def __init__(self):\n        self.capacity = 100\n        self.queue = []\n        self.log_file = \"fifo_log.txt\"\n\n    def add(self, item):\n        if len(self.queue) >= self.capacity:\n            self.queue.pop(0)\n        self.queue.append((item, datetime.now()))\n\n    def prompt(self):\n        return \"\\n\".join([f\"{time} - {text}\" for text, time in reversed(self.queue)])\n```\n\n状态在转换时将行为记录到内存中，LLM在决策时会参考这些历史记录来生成更智能的下一状态选择。\n\n资料来源：[examples/bilibili_surfer/fifo.py:1-30](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n\n## 线程安全机制\n\nCyclicExecutor使用`threading.Lock`保护共享状态，确保多线程环境下的安全访问：\n\n```python\nclass CyclicExecutor:\n    def __init__(self, default_time_interval: float):\n        self.running = False\n        self.lock = threading.Lock()\n        # ...\n\n    def pause(self):\n        with self.lock:\n            self.running = False\n\n    def resume(self):\n        with self.lock:\n            self.running = True\n```\n\n`with self.lock`语句确保在修改`running`标志时获得锁，防止竞态条件。由于Python的GIL特性，这种粗粒度的锁策略在大多数场景下已经足够安全。\n\n资料来源：[cyclic_agent/executor.py:8-34](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n\n## 模块导出\n\ncyclic_agent包的公共接口通过`__init__.py`导出：\n\n```python\nfrom cyclic_agent.state import State\nfrom cyclic_agent.executor import CyclicExecutor\n\n__all__ = [\"State\", \"CyclicExecutor\"]\n```\n\n使用者只需导入这两个核心组件即可开始构建自主代理应用。\n\n资料来源：[cyclic_agent/__init__.py:1-6](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/__init__.py)\n\n## 最佳实践\n\n### 初始化配置\n\n| 配置项 | 说明 | 推荐值 |\n|--------|------|--------|\n| default_time_interval | 状态转换间隔（秒） | 3-10秒 |\n| 初始状态选择 | 应选择有明确转换路径的状态 | 确保能进入循环 |\n\n### 状态设计原则\n\n1. **单一职责**：每个状态应专注于特定功能领域\n2. **幂等性**：状态的`next()`方法应能安全重复调用\n3. **状态保持**：使用Pydantic的`model_dump()`传递上下文数据\n4. **类型约束**：通过Type Alias明确状态的可达转换\n\n### 资源管理\n\n- 长时间运行的应用应设置外部超时机制\n- 使用`kill()`方法确保程序能正常退出\n- 配合外部信号（如SIGTERM）实现优雅关闭\n\n---\n\n<a id='page-6'></a>\n\n## 有限状态机模式\n\n### 相关页面\n\n相关主题：[State基类设计](#page-4), [CyclicExecutor执行器](#page-5)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [cyclic_agent/state.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/state.py)\n- [cyclic_agent/executor.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n- [examples/bilibili_surfer/bilibili_surfer.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n- [examples/hello_world/hello_world.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/hello_world/hello_world.py)\n- [cyclic_agent/__init__.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/__init__.py)\n- [examples/bilibili_surfer/fifo.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n</details>\n\n# 有限状态机模式\n\n## 概述\n\nCyclicAgent 框架的核心设计理念是将智能代理（Agent）抽象为**有限状态机（Finite State Machine, FSM）**。这一设计采用了状态模式（State Design Pattern），使代理能够根据内部状态属性（如记忆、元提示等）以及外部信号，在不同状态之间进行推断和转换。\n\n在 CyclicAgent 中，所有状态都实现了状态转换函数，该函数返回另一个状态。这种设计允许状态转换操作无限进行，从而使代理形成\"循环\"执行模式。资料来源：[README.md]()\n\n## 核心组件\n\n### State 基类\n\n`State` 是整个框架的抽象基类，定义在 `cyclic_agent/state.py` 中。它使用了 Python 的泛型语法来表示状态可接收的信号类型。\n\n```python\nclass State[SigT](BaseModel):\n    @abstractmethod\n    def next(self, signal: SigT | None = None) -> State[SigT]:\n        \"\"\"Transition to the next state.\"\"\"\n        raise NotImplementedError\n```\n\n| 属性/方法 | 类型 | 说明 |\n|-----------|------|------|\n| `SigT` | 泛型类型参数 | 表示状态可接收的信号类型 |\n| `next(signal)` | 抽象方法 | 执行状态转换，返回下一个状态 |\n| `model_dump()` | 继承自 BaseModel | 序列化状态对象为字典 |\n\nState 类继承自 Pydantic 的 `BaseModel`，这意味着所有具体状态都自动具备以下能力：\n\n- 自动数据验证\n- JSON 序列化/反序列化\n- 类型提示支持\n\n资料来源：[cyclic_agent/state.py:8-13]()\n\n### CyclicExecutor 执行器\n\n`CyclicExecutor` 负责运行状态机，通过独立的线程持续执行状态转换循环。\n\n```python\nclass CyclicExecutor:\n    def __init__(self, default_time_interval: float):\n        self.running = False\n        self.lock = threading.Lock()\n        self.default_time_interval = default_time_interval\n        self.killed = False\n        self.thread = None\n```\n\n| 方法 | 说明 |\n|------|------|\n| `start(initial_state)` | 启动执行器，传入初始状态 |\n| `pause()` | 暂停状态机执行 |\n| `resume()` | 恢复状态机执行 |\n| `kill()` | 终止执行器 |\n| `_main_loop()` | 内部主循环，持续调用 `state.next()` |\n\n执行器使用线程安全的方式管理状态转换：\n\n```python\ndef _main_loop(self, state: State) -> None:\n    while True:\n        if self.killed:\n            return\n        if self.running:\n            state = state.next()\n            time.sleep(self.default_time_interval)\n```\n\n资料来源：[cyclic_agent/executor.py:1-36]()\n\n## 架构图\n\n```mermaid\ngraph TD\n    A[初始状态 StartState] -->|next()| B[状态 B]\n    B -->|next()| C[状态 C]\n    C -->|next()| D[...]\n    D -->|next()| E[状态 N]\n    E -->|next()| A\n    \n    F[CyclicExecutor] -->|管理| A\n    F -->|管理| B\n    F -->|管理| C\n    \n    G[Signal] -.->|可选输入| A\n    G -.->|可选输入| B\n    G -.->|可选输入| C\n    \n    H[Memory Context] -.->|状态上下文| A\n    H -.->|状态上下文| B\n```\n\n## 状态转换机制\n\n### 基础转换模式\n\n最简单的状态转换是两个状态之间的循环切换，如 hello_world 示例所示：\n\n```python\nclass AskQuestion(State[None]):\n    def next(self, signal: None = None) -> AnswerQuestion:\n        response = co.chat(message=\"Ask a question\", temperature=1)\n        return AnswerQuestion(question=response.text)\n\n\nclass AnswerQuestion(State[None]):\n    question: str\n\n    def next(self, signal: None = None) -> AskQuestion:\n        answer = co.chat(message=self.question)\n        return AskQuestion()\n```\n\n每个状态通过 `next()` 方法返回下一个状态，形成无限循环。资料来源：[examples/hello_world/hello_world.py:10-27]()\n\n### 类型联合定义可达状态\n\nCyclicAgent 使用 Python 的类型别名（Type Alias）和 `type` 声明来明确每个状态可以转换到哪些其他状态：\n\n```python\ntype BrowsingVideoReachable = Union[BrowsingVideo, ReadingComments]\n\nclass BrowsingVideo(BilibiliStateBase):\n    @overrides\n    def next(self, signal: None = None) -> BrowsingVideoReachable:\n        # ... 逻辑处理\n        match self._infer_state_helper('BrowsingVideo', 'ReadingComments'):\n            case 'BrowsingVideo':\n                return self\n            case 'ReadingComments':\n                return ReadingComments(**self.model_dump(), ...)\n```\n\n这种设计提供了：\n\n- **类型安全**：静态检查状态转换的合法性\n- **IDE 支持**：自动补全和导航\n- **文档化**：明确每个状态的转换路径\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:44-59]()\n\n### 使用 match-case 进行状态推断\n\n在实际应用中，状态转换往往需要根据 LLM 的响应来决定。CyclicAgent 使用 `match-case` 语法匹配 LLM 返回的状态名称：\n\n```python\nmatch self._infer_state_helper('BrowsingVideo', 'ReadingComments', 'PostComment'):\n    case 'BrowsingVideo':\n        return BrowsingVideo(**self.model_dump(exclude={...}))\n    case 'ReadingComments':\n        return self\n    case 'PostComment':\n        return PostComment(**self.model_dump(), reply_to=cmt['content']['message'], ...)\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:93-100]()\n\n## 状态上下文与记忆\n\n### BilibiliStateBase 基础状态类\n\n示例项目中的 `BilibiliStateBase` 展示了如何为状态添加共享上下文：\n\n```python\nclass BilibiliStateBase(State[None], ABC):\n    model_config = ConfigDict(arbitrary_types_allowed=True)\n    initial_prompt: str\n    memory: Fifo\n    co: Client\n    credential: Credential\n```\n\n| 上下文属性 | 类型 | 说明 |\n|-----------|------|------|\n| `initial_prompt` | str | 初始化 LLM 交互的提示词 |\n| `memory` | Fifo | FIFO 队列，记录历史行为 |\n| `co` | Client | Cohere LLM 客户端 |\n| `credential` | Credential | Bilibili API 认证凭证 |\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:28-35]()\n\n### FIFO 记忆组件\n\n`Fifo` 类实现了有限容量的先进先出队列，用于存储代理的历史行为：\n\n```python\nclass Fifo:\n    def __init__(self):\n        self.capacity = 100\n        self.queue = []\n        self.log_file = \"fifo_log.txt\"\n\n    def add(self, item):\n        if len(self.queue) >= self.capacity:\n            self.queue.pop(0)  # 移除最旧的记录\n        timestamp = datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n        self.queue.append((item, timestamp))\n        self.log_to_file(item, timestamp)\n\n    def prompt(self):\n        return \"\\n\".join([f\"{time} - {text}\" for text, time in reversed(self.queue)])\n```\n\n| 方法 | 说明 |\n|------|------|\n| `add(item)` | 添加新记录，自动管理容量上限 |\n| `prompt()` | 生成提示字符串，最新记录在前 |\n| `log_to_file()` | 将记录持久化到日志文件 |\n\n资料来源：[examples/bilibili_surfer/fifo.py:1-34]()\n\n## 完整工作流程图\n\n```mermaid\nsequenceDiagram\n    participant User as 用户\n    participant Executor as CyclicExecutor\n    participant State as 当前状态\n    participant LLM as LLM API\n    participant Memory as 记忆组件\n    participant Env as 外部环境\n\n    User->>Executor: start(initial_state)\n    loop 持续执行\n        Executor->>State: next(signal?)\n        State->>Memory: prompt() 获取历史\n        State->>State: 构建决策提示\n        State->>LLM: chat(prompt)\n        LLM-->>State: 返回决策结果\n        State->>State: match-case 匹配结果\n        State->>State: model_dump() 传递上下文\n        State->>Env: 执行动作（如发帖、评论）\n        State-->>Executor: 返回下一状态\n        Executor->>Executor: sleep(interval)\n    end\n```\n\n## 导出接口\n\nCyclicAgent 包仅导出两个核心类供用户使用：\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\n```\n\n| 导出项 | 来源文件 | 说明 |\n|-------|----------|------|\n| `State` | cyclic_agent/state.py | 状态机抽象基类 |\n| `CyclicExecutor` | cyclic_agent/executor.py | 状态机执行器 |\n\n资料来源：[cyclic_agent/__init__.py:1-6]()\n\n## 使用示例\n\n### 最小示例：问答循环\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\n\nclass AskQuestion(State[None]):\n    def next(self, signal=None) -> AnswerQuestion:\n        response = co.chat(message=\"Ask a question\")\n        return AnswerQuestion(question=response.text)\n\nclass AnswerQuestion(State[None]):\n    question: str\n    def next(self, signal=None) -> AskQuestion:\n        answer = co.chat(message=self.question)\n        return AskQuestion()\n\n# 启动执行器\nexecutor = CyclicExecutor(5)  # 每次转换间隔 5 秒\nexecutor.start(AskQuestion())\n```\n\n### Bilibili 冲浪代理\n\n完整的 Bilibili 冲浪代理展示了复杂的实际应用场景，包含四个状态：\n\n| 状态 | 可达状态 | 功能 |\n|------|----------|------|\n| `BrowsingVideo` | `BrowsingVideo`, `ReadingComments` | 搜索和浏览视频 |\n| `ReadingComments` | `BrowsingVideo`, `ReadingComments`, `PostComment` | 阅读视频评论 |\n| `PostComment` | `BrowsingVideo` | 回复评论 |\n| 初始状态 | `BrowsingVideo` | 从视频浏览开始 |\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:44-140]()\n\n## 设计优势\n\n| 优势 | 说明 |\n|------|------|\n| **状态内聚** | 每个状态包含自身数据和转换逻辑 |\n| **易于扩展** | 添加新状态只需继承 `State` 并实现 `next()` |\n| **类型安全** | 静态类型检查确保状态转换的合法性 |\n| **测试友好** | 每个状态可独立单元测试 |\n| **无限循环** | CyclicExecutor 支持状态机持续运行 |\n| **上下文传递** | 通过 Pydantic 的 `model_dump()` 传递状态属性 |\n\n## 注意事项\n\n1. **泛型类型**：`from __future__ import annotations` 是必需的，用于支持前向引用语法\n2. **线程安全**：`CyclicExecutor` 内部使用锁保护共享状态\n3. **状态不可变性**：建议状态对象设计为不可变或使用 Pydantic 的深拷贝机制\n4. **信号机制**：当前实现中 `signal` 参数默认为 `None`，可根据需要扩展\n\n---\n\n<a id='page-7'></a>\n\n## Search状态模块\n\n### 相关页面\n\n相关主题：[CoT状态模块](#page-8), [有限状态机模式](#page-6)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [cyclic_agent/search.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/search.py)\n- [cyclic_agent/state.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/state.py)\n- [cyclic_agent/__init__.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/__init__.py)\n- [cyclic_agent/executor.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n- [examples/bilibili_surfer/bilibili_surfer.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n- [examples/bilibili_surfer/fifo.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n</details>\n\n# Search状态模块\n\n## 概述\n\nSearch状态模块是CyclicAgent框架中用于封装搜索功能的核心组件。该模块通过继承`State`基类实现了一个专门处理搜索查询的状态类型，允许代理（Agent）在状态机中执行搜索操作并根据搜索结果进行状态转换。\n\nSearch模块采用了策略模式设计，`search`方法被声明为抽象方法（`NotImplementedError`），由子类实现具体的搜索逻辑。这种设计使得Search状态模块具有高度的灵活性和可扩展性，可以适配各种不同的搜索数据源和搜索API。 资料来源：[cyclic_agent/search.py:1-15]()\n\n## 架构设计\n\n### 类结构\n\n```mermaid\nclassDiagram\n    class State~SigT~ {\n        <<abstract>>\n        +next(signal: SigT | None) State\n    }\n    \n    class Search {\n        +query: str\n        +exit_: Callable\n        +next(signal: None) State\n        +search(query: str) str\n    }\n    \n    State <|-- Search : 继承\n```\n\nSearch类继承自`State[None]`基类，这意味着该状态的信号类型为`None`。状态在执行`next()`方法时不需要外部信号输入，而是直接执行内置的搜索逻辑。 资料来源：[cyclic_agent/state.py:1-18]()[cyclic_agent/search.py:5]()\n\n### 类型定义\n\n| 属性名 | 类型 | 说明 |\n|--------|------|------|\n| `query` | `str` | 搜索查询字符串，包含用户或代理要搜索的关键词 |\n| `exit_` | `Callable[[Annotated[str, \"search result\"]], State]` | 退出回调函数，接收搜索结果字符串作为参数，返回下一个状态 |\n\n回调函数的`Annotated`注解用于标记搜索结果的语义含义，便于类型检查和代码文档化。 资料来源：[cyclic_agent/search.py:6-7]()\n\n## 核心方法\n\n### next方法\n\n`next`方法是Search状态的状态转换实现。当执行器调用此方法时，会触发搜索操作并通过回调函数返回下一个状态。\n\n```mermaid\ngraph TD\n    A[执行器调用 next] --> B[执行 searchquery]\n    B --> C[获取搜索结果]\n    C --> D[调用 exit_ 回调]\n    D --> E[返回下一状态]\n```\n\n方法签名如下：\n\n```python\ndef next(self, signal: None = None) -> State:\n    search_result = self.search(self.query)\n    return self.exit_(search_result)\n```\n\n该方法接收一个可选的`signal`参数（类型为`None`），这是由于继承自泛型`State[None]`基类的接口要求。在实际执行中，`signal`参数不会被使用，搜索所需的查询内容已经存储在实例的`query`属性中。 资料来源：[cyclic_agent/search.py:9-12]()\n\n### search方法\n\n`search`方法是抽象搜索逻辑的占位符实现，设计者意图由子类重写此方法以提供具体的搜索功能。\n\n```python\ndef search(self, query: str) -> str:\n    raise NotImplementedError\n```\n\n该方法接收一个`query`字符串参数，返回搜索结果的字符串表示。在基类中直接抛出`NotImplementedError`异常，要求子类必须实现具体的搜索逻辑。开发者可以在子类中接入各种搜索服务，如全文搜索引擎、API调用、数据库查询等。 资料来源：[cyclic_agent/search.py:14-15]()\n\n## 使用模式\n\n### 基本集成流程\n\n在CyclicAgent框架中，Search状态通常与其他状态配合使用，形成完整的工作流。以下是在状态机中集成Search状态的典型模式：\n\n1. **定义Search子类**：继承`Search`类并实现`search`方法\n2. **配置退出回调**：在初始化时传入`exit_`回调函数，用于处理搜索结果\n3. **与执行器配合**：将Search状态作为初始状态或中间状态交给`CyclicExecutor`执行\n\n```mermaid\ngraph LR\n    A[其他状态] -->|转换| B[Search状态]\n    B -->|执行搜索| C[获取结果]\n    C -->|回调| D[下一状态]\n    D -->|循环| A\n```\n\n### 与Fifo内存组件配合\n\n在真实应用场景中（如B站冲浪示例），Search操作通常与`Fifo`内存组件配合使用。`Fifo`类实现了一个容量为100的先进先出队列，用于记录代理的历史行为：\n\n```python\nclass Fifo:\n    def __init__(self):\n        self.capacity = 100\n        self.queue = []\n        self.log_file = \"fifo_log.txt\"\n```\n\n每次执行搜索后，搜索关键词会被记录到内存中，帮助代理在后续决策时考虑历史上下文。 资料来源：[examples/bilibili_surfer/fifo.py:1-17]()\n\n### 实际应用示例\n\n在B站冲浪代理中，虽然没有直接继承`Search`类，但展示了类似的搜索模式实现：\n\n```python\nasync def search_by_type(response,\n                         search_type=search.SearchObjectType.VIDEO,\n                         order_type=search.OrderUser.FANS,\n                         order_sort=0):\n    # 实现B站视频搜索\n```\n\n代理通过生成搜索关键词、调用搜索API、解析结果、选择目标视频等步骤，形成完整的搜索-决策工作流。这种模式与Search状态模块的设计理念高度一致。 资料来源：[examples/bilibili_surfer/bilibili_surfer.py:1-120]()\n\n## 与框架其他组件的关系\n\n### 与State基类的关系\n\nSearch是`State`基类的具体实现，遵循状态模式的设计原则。每个状态必须实现`next`方法，该方法返回下一个要转换到的状态。Search类在`next`方法中嵌入了搜索执行逻辑，使得状态转换与业务逻辑紧密结合。 资料来源：[cyclic_agent/state.py:5-9]()\n\n### 与CyclicExecutor的关系\n\n`CyclicExecutor`负责管理和执行状态机的循环：\n\n```python\nclass CyclicExecutor:\n    def __init__(self, default_time_interval: float):\n        self.running = False\n        self.lock = threading.Lock()\n        self.default_time_interval = default_time_interval\n```\n\n执行器在每个时间间隔调用当前状态的`next`方法获取下一个状态，从而推动状态机向前运行。当Search状态被设置为当前状态时，执行器会触发其`next`方法执行搜索操作。 资料来源：[cyclic_agent/executor.py:1-40]()\n\n### 模块导出\n\nSearch类作为`cyclic_agent`包的一部分被导出，与核心组件`State`和`CyclicExecutor`一起构成框架的基础API：\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\n```\n\nSearch类本身未包含在`__all__`列表中，这可能意味着它被视为内部实现或需要直接从子模块导入：\n\n```python\nfrom cyclic_agent.search import Search\n```\n\n## 扩展指南\n\n### 实现自定义Search子类\n\n开发者可以通过继承Search类来实现特定数据源的搜索功能：\n\n```python\nfrom cyclic_agent.search import Search\nfrom cyclic_agent import State\n\nclass WebSearch(Search):\n    def search(self, query: str) -> str:\n        # 实现网络搜索逻辑\n        results = some_search_api.search(query)\n        return str(results)\n    \n    def handle_results(self, results: str) -> State:\n        # 处理搜索结果，决定下一状态\n        return SomeDecisionState(results=results)\n\n# 使用示例\ninitial_state = WebSearch(\n    query=\"Python最佳实践\",\n    exit_=lambda results: WebSearch(query=f\"关于{results}的详细信息\")\n)\n```\n\n### 集成外部搜索API\n\nSearch模块的灵活性使其可以与各种外部搜索服务集成：\n\n| 搜索服务 | 集成方式 | 适用场景 |\n|----------|----------|----------|\n| Elasticsearch | 同步HTTP请求 | 全文搜索 |\n| Algolia | SDK调用 | 应用内搜索 |\n| Bing/Google API | REST API | 网络搜索 |\n| 数据库全文索引 | SQL查询 | 结构化数据搜索 |\n\n## 设计理念\n\nSearch状态模块体现了CyclicAgent框架的几个核心设计原则：\n\n1. **状态即行为**：每个状态封装了特定的行为逻辑，搜索操作被建模为状态而非普通方法\n2. **回调驱动的状态转换**：通过`exit_`回调函数实现搜索结果与状态转换的解耦\n3. **抽象与实现分离**：`search`方法的抽象声明允许子类提供不同实现，保持框架核心稳定\n4. **有限状态机语义**：状态只能转换到`exit_`回调指定的下一状态，维持状态机的可预测性\n\n这种设计使得代理系统既能执行复杂的搜索任务，又能保持清晰的状态流转逻辑，便于调试和扩展。\n\n---\n\n<a id='page-8'></a>\n\n## CoT状态模块\n\n### 相关页面\n\n相关主题：[Search状态模块](#page-7)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [cyclic_agent/cot.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/cot.py)\n- [cyclic_agent/state.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/state.py)\n- [cyclic_agent/executor.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n- [cyclic_agent/__init__.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/__init__.py)\n- [examples/hello_world/hello_world.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/hello_world/hello_world.py)\n</details>\n\n# CoT状态模块\n\n## 概述\n\nCoT（Chain of Thought，思维链）状态模块是CyclicAgent框架中的一个核心组件，专门用于实现链式思维推理能力。该模块继承自基础`State`类，通过在提示词后附加\"Let's think step by step.\"指令，引导大语言模型（LLM）进行逐步推理，并将推理结果通过回调机制传递给下一个状态。\n\nCoT状态模块的设计遵循有限状态机（FSM）模式，允许在复杂的代理（Agent）工作流中无缝集成思维链推理能力。资料来源：[cyclic_agent/cot.py:1-18]()\n\n## 核心架构\n\n### 类定义与继承关系\n\n```\nState[SigT] (抽象基类)\n    └── CoT (思维链状态)\n```\n\n`CoT`类继承自`State[None]`，这意味着它是一个无信号类型的状态类。资料来源：[cyclic_agent/cot.py:5]()\n\n### 组件构成\n\n| 组件名称 | 类型 | 说明 |\n|---------|------|------|\n| `exit_` | `Callable[[str], State]` | 退出回调函数，接收LLM输出并返回下一个状态 |\n| `llm` | `State` | 底层LLM状态处理器，负责与语言模型交互 |\n| `prompt` | `str` | 用户提供的原始提示词 |\n\n资料来源：[cyclic_agent/cot.py:6-8]()\n\n## 工作原理\n\n### 思维链增强机制\n\n当`CoT`状态的`next()`方法被调用时，会自动对原始提示词进行思维链增强处理。具体流程如下：\n\n```python\ndef next(self, signal: None = None) -> State:\n    prompt = self.prompt + \"Let's think step by step.\"\n    \n    def callback(answer: str) -> State:\n        return self.exit_(answer)\n    \n    return self.llm(prompt=prompt, callback=callback)\n```\n\n1. **提示词增强**：将\"Let's think step by step.\"追加到原始`prompt`末尾\n2. **回调闭包**：创建一个内部`callback`函数，捕获`exit_`回调\n3. **状态传递**：将增强后的提示词和回调传递给底层LLM状态\n\n资料来源：[cyclic_agent/cot.py:10-17]()\n\n### 状态转换流程\n\n```mermaid\ngraph TD\n    A[CoT.next 调用] --> B[拼接思维链提示词]\n    B --> C[调用 LLM 处理]\n    C --> D[获取模型输出]\n    D --> E[触发 callback]\n    E --> F[执行 exit_ 回调]\n    F --> G[返回下一个 State]\n```\n\n## 与State基类的关系\n\n### 抽象基类定义\n\n`State`是一个使用Pydantic的`BaseModel`实现的泛型抽象类，定义了状态转换的核心接口：\n\n```python\nclass State[SigT](BaseModel):\n    @abstractmethod\n    def next(self, signal: SigT | None = None) -> State[SigT]:\n        \"\"\"Transition to the next state.\"\"\"\n        raise NotImplementedError\n```\n\n资料来源：[cyclic_agent/state.py:6-11]()\n\n### 接口契约\n\n| 方法 | 参数 | 返回值 | 说明 |\n|-----|------|--------|------|\n| `next` | `signal: SigT \\| None` | `State[SigT]` | 执行状态转换，返回下一个状态 |\n\n`CoT`类完整实现了这一接口，确保与CyclicExecutor执行器的兼容性。\n\n## 执行器集成\n\n`CyclicExecutor`负责管理和调度所有状态，包括`CoT`状态。执行器采用独立线程运行主循环，周期性地调用状态的`next()`方法：\n\n```python\ndef _main_loop(self, state: State) -> None:\n    while True:\n        if self.killed:\n            return\n\n        if self.running:\n            state = state.next()\n            time.sleep(self.default_time_interval)\n```\n\n资料来源：[cyclic_agent/executor.py:33-39]()\n\n### 执行流程图\n\n```mermaid\ngraph TD\n    A[CyclicExecutor.start] --> B[创建工作线程]\n    B --> C[_main_loop 运行]\n    C --> D{检查 running?}\n    D -->|否| E[等待]\n    E --> D\n    D -->|是| F[调用 state.next]\n    F --> G[获取下一个状态]\n    G --> H[休眠 default_time_interval]\n    H --> C\n```\n\n## 使用模式\n\n### 基础使用结构\n\n在实际应用中，`CoT`状态通常与其他自定义状态结合使用。以下是基于Hello World示例的典型模式：\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\nfrom cyclic_agent.cot import CoT\n\nclass MyLLM(State[None]):\n    prompt: str\n    callback: Callable[[str], State]\n    \n    def next(self, signal=None) -> State:\n        # 调用LLM API获取回答\n        response = llm.chat(message=self.prompt)\n        return self.callback(response.text)\n\nclass MyExitState(State[None]):\n    result: str\n    \n    def next(self, signal=None) -> State:\n        print(f\"最终结果: {self.result}\")\n        return self  # 或返回其他状态\n```\n\n### 回调机制详解\n\n`exit_`回调是连接CoT状态与下游处理的关键机制。它允许：\n\n- **动态状态路由**：根据LLM输出决定下一步状态\n- **上下文传递**：将推理结果携带到新状态\n- **条件分支**：实现复杂的条件逻辑\n\n## 模块导出\n\n`CoT`类通过`cyclic_agent.cot`模块导出，可通过以下方式导入：\n\n```python\nfrom cyclic_agent.cot import CoT\n```\n\n资料来源：[cyclic_agent/cot.py:1]()\n\n## 设计优势\n\n| 优势 | 说明 |\n|------|------|\n| **解耦设计** | CoT逻辑与LLM交互分离，便于单元测试 |\n| **可组合性** | 可与任何实现`State`接口的组件配合使用 |\n| **回调灵活性** | 允许外部控制状态转换逻辑 |\n| **框架兼容** | 无缝集成到CyclicExecutor状态机执行体系 |\n\n## 与其他状态的关系\n\n在CyclicAgent框架中，`CoT`状态与其他状态类型形成互补：\n\n```mermaid\ngraph LR\n    A[CoT] -->|思维链推理| B[普通State]\n    C[Search] -->|搜索增强| B\n    D[自定义状态] -->|领域逻辑| B\n    B --> E[CyclicExecutor]\n```\n\n- **CoT**：提供链式推理能力\n- **Search**：提供搜索增强能力\n- **自定义State**：处理特定业务逻辑\n\n## 总结\n\nCoT状态模块是CyclicAgent框架实现自主代理智能推理的核心组件。通过在提示词中嵌入思维链指令，该模块能够引导大语言模型进行更深入、更结构化的思考。结合状态机模式和回调机制，CoT状态为构建复杂、可扩展的AI代理系统提供了坚实的技术基础。\n\n---\n\n<a id='page-9'></a>\n\n## Hello World示例\n\n### 相关页面\n\n相关主题：[快速入门指南](#page-3), [Bilibili Surfer示例](#page-10)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [examples/hello_world/hello_world.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/hello_world/hello_world.py)\n- [cyclic_agent/state.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/state.py)\n- [cyclic_agent/executor.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n- [cyclic_agent/__init__.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/__init__.py)\n- [cyclic_agent/cot.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/cot.py)\n</details>\n\n# Hello World示例\n\n## 概述\n\nHello World示例是CyclicAgent框架的入门级演示项目，展示了如何使用状态机模式构建自主运行的AI代理。该示例创建了两个相互转换的状态，形成一个无限循环的问答系统。资料来源：[examples/hello_world/hello_world.py:1-27]()\n\n## 核心概念\n\n### 状态设计模式\n\nCyclicAgent将代理抽象为有限状态机（FSM），每个状态实现状态转换函数，返回另一个状态。这种设计允许状态转换操作无限进行，从而实现代理的“循环”特性。资料来源：[README.md:1-20]()\n\n### 状态基类\n\n所有状态必须继承`State`抽象基类，并实现`next()`方法。`State`类使用Pydantic的`BaseModel`，支持类型注解和自动验证。资料来源：[cyclic_agent/state.py:1-15]()\n\n## 系统架构\n\n### 组件关系图\n\n```mermaid\ngraph TD\n    A[AskQuestion 状态] -->|next()| B[AnswerQuestion 状态]\n    B -->|next()| A\n    C[CyclicExecutor] -->|管理执行| A\n    C -->|管理执行| B\n```\n\n### 类结构\n\n| 类名 | 文件位置 | 继承关系 | 职责 |\n|------|---------|---------|------|\n| `State` | cyclic_agent/state.py | BaseModel | 状态基类，定义`next()`抽象方法 |\n| `CyclicExecutor` | cyclic_agent/executor.py | - | 执行器，管理状态机的运行、暂停、终止 |\n| `AskQuestion` | examples/hello_world/hello_world.py | State[None] | 提问状态 |\n| `AnswerQuestion` | examples/hello_world/hello_world.py | State[None] | 回答状态 |\n\n## 状态实现详解\n\n### AskQuestion状态\n\n```python\nclass AskQuestion(State[None]):\n    def next(self, signal: None = None) -> AnswerQuestion:\n        response = co.chat(message=\"Ask a question\", temperature=1)\n        print(response.text)\n        return AnswerQuestion(question=response.text)\n```\n\n该状态负责生成问题，使用Cohere API进行对话生成，温度参数设为1以获得更具创造性的输出。状态转换到`AnswerQuestion`，携带生成的问题内容。资料来源：[examples/hello_world/hello_world.py:17-22]()\n\n### AnswerQuestion状态\n\n```python\nclass AnswerQuestion(State[None]):\n    question: str\n\n    def next(self, signal: None = None) -> AskQuestion:\n        answer = co.chat(message=self.question)\n        print(answer)\n        return AskQuestion()\n```\n\n该状态持有问题内容字段`question`，使用Cohere API获取回答后，转换回`AskQuestion`状态，形成循环。资料来源：[examples/hello_world/hello_world.py:24-30]()\n\n## CyclicExecutor执行器\n\n### 核心功能\n\n`CyclicExecutor`类负责在独立线程中运行状态机，支持运行控制操作。资料来源：[cyclic_agent/executor.py:1-42]()\n\n| 方法 | 功能描述 |\n|------|---------|\n| `start(initial_state)` | 启动执行器，使用独立线程运行状态机 |\n| `pause()` | 暂停状态转换 |\n| `resume()` | 恢复状态转换 |\n| `kill()` | 终止执行器 |\n\n### 执行流程\n\n```mermaid\nsequenceDiagram\n    participant User\n    participant Executor\n    participant State\n    \n    User->>Executor: start(initial_state)\n    loop 状态循环\n        Executor->>State: state.next()\n        State-->>Executor: next_state\n        Executor->>Executor: sleep(default_time_interval)\n    end\n    User->>Executor: kill()\n```\n\n### 线程管理实现\n\n执行器使用`threading.Thread`在后台线程中运行主循环，通过锁机制确保线程安全的状态控制。资料来源：[cyclic_agent/executor.py:16-23]()\n\n## 配置与环境\n\n### 依赖项\n\n| 依赖包 | 用途 |\n|-------|------|\n| cohere | LLM对话API客户端 |\n| python-dotenv | 环境变量管理 |\n| cyclic_agent | 核心框架 |\n\n### 环境变量\n\n| 变量名 | 说明 |\n|-------|------|\n| COHERE_API_KEY | Cohere API密钥 |\n\n```python\nfrom dotenv import load_dotenv\nload_dotenv()\nco = cohere.Client(os.environ.get(\"COHERE_API_KEY\"))\n```\n\n资料来源：[examples/hello_world/hello_world.py:7-10]()\n\n## 运行示例\n\n### 代码\n\n```python\nif __name__ == \"__main__\":\n    initial_state = AskQuestion()\n    executor = CyclicExecutor(5)\n    executor.start(initial_state)\n    time.sleep(20)\n```\n\n### 参数说明\n\n| 参数 | 值 | 说明 |\n|------|-----|------|\n| default_time_interval | 5 | 每次状态转换间隔5秒 |\n| sleep时间 | 20 | 程序运行20秒后退出 |\n\n## 进阶示例参考\n\n除了Hello World示例外，仓库还提供了更复杂的示例：\n\n| 示例名称 | 文件路径 | 特性 |\n|---------|---------|------|\n| Chain of Thought | cyclic_agent/cot.py | 思维链模式 |\n| Search | cyclic_agent/search.py | 搜索功能封装 |\n| Bilibili冲浪者 | examples/bilibili_surfer/ | 完整代理实现 |\n\n### CoT（思维链）示例\n\n`CoT`类展示了如何实现思维链模式，通过在提示词后添加\"Let's think step by step.\"引导模型分步骤推理。资料来源：[cyclic_agent/cot.py:1-16]()\n\n## 总结\n\nHello World示例演示了CyclicAgent框架的核心用法：\n\n1. **状态定义**：继承`State`基类，实现`next()`方法\n2. **状态转换**：通过`next()`方法返回下一个状态\n3. **执行管理**：使用`CyclicExecutor`控制状态机运行\n4. **无限循环**：状态间相互转换形成闭环\n\n该框架的核心理念是将AI代理建模为有限状态机，每个状态根据内部属性和外部信号推理下一状态，实现自主、循环的代理行为。\n\n---\n\n<a id='page-10'></a>\n\n## Bilibili Surfer示例\n\n### 相关页面\n\n相关主题：[Hello World示例](#page-9)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [examples/bilibili_surfer/bilibili_surfer.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n- [examples/bilibili_surfer/fifo.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n- [cyclic_agent/state.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/state.py)\n- [cyclic_agent/executor.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/executor.py)\n- [cyclic_agent/__init__.py](https://github.com/xingjianll/cyclic-agent/blob/main/cyclic_agent/__init__.py)\n</details>\n\n# Bilibili Surfer示例\n\n## 概述\n\nBilibili Surfer是cyclic-agent框架的一个完整示例应用，演示了如何构建一个自主运行的AI代理，使其能够像真实用户一样浏览Bilibili视频网站、阅读评论并自动回复。该示例展示了有限状态机（FSM）设计模式在实际应用中的强大能力，将AI代理的行为抽象为多个可相互转换的状态，每个状态根据内部属性和外部信号推断下一个状态。\n\n这个示例的核心价值在于它演示了如何将复杂的AI行为与外部API集成。通过结合Cohere大语言模型和Bilibili API，系统能够理解自然语言指令，做出合理的决策，并在视频网站上执行实际操作。整个系统运行在CyclicExecutor的调度下，按照预设的时间间隔不断循环执行状态转换，直到达到预设的迭代次数或被手动终止。\n\n## 系统架构\n\n### 整体架构图\n\n```mermaid\ngraph TD\n    A[CyclicExecutor] -->|启动| B[BrowsingVideo状态]\n    B -->|搜索视频| C{LLM决策}\n    C -->|BrowsingVideo| B\n    C -->|ReadingComments| D[ReadingComments状态]\n    D -->|选择评论| C\n    C -->|PostComment| E[PostComment状态]\n    E -->|完成回复| B\n    B -->|记录| F[Fifo内存]\n    D -->|记录| F\n    E -->|记录| F\n```\n\n### 核心组件层次\n\n系统采用分层架构设计，从底层到顶层依次为：\n\n1. **核心框架层**（cyclic_agent包）\n   - `State`基类：定义所有状态的抽象接口\n   - `CyclicExecutor`：状态机执行器，负责驱动状态循环\n   - `Search`、`CoT`等辅助组件\n\n2. **基础服务层**\n   - `Fifo`：内存管理组件，持久化记录代理行为历史\n   - Bilibili API集成：通过bilibili_api库访问B站服务\n\n3. **业务逻辑层**\n   - `BilibiliStateBase`：所有业务状态的基类\n   - `BrowsingVideo`、`ReadingComments`、`PostComment`：具体业务状态\n\n4. **AI决策层**\n   - Cohere Client：大语言模型集成\n   - 提示词模板：指导AI做出合理的决策\n\n## 状态机设计\n\n### 状态定义\n\n系统定义了三种主要状态，每种状态都继承自`BilibiliStateBase`，而`BilibiliStateBase`又继承自`State[None]`基类。\n\n| 状态类名 | 功能描述 | 主要属性 |\n|---------|---------|---------|\n| `BrowsingVideo` | 搜索并浏览视频 | 无特殊属性，继承基类属性 |\n| `ReadingComments` | 阅读视频下的热门评论 | `video_bvid`、`video_title`、`video_description` |\n| `PostComment` | 回复选定的评论 | 包含`reply_to`、`reply_to_oid`用于定位回复目标 |\n\n### 状态转换关系\n\n```mermaid\nstateDiagram-v2\n    [*] --> BrowsingVideo\n    BrowsingVideo --> BrowsingVideo: 返回继续浏览\n    BrowsingVideo --> ReadingComments: 选择评论\n    ReadingComments --> BrowsingVideo: 返回视频浏览\n    ReadingComments --> ReadingComments: 继续读评论\n    ReadingComments --> PostComment: 选择回复\n    PostComment --> BrowsingVideo: 完成回复\n```\n\n### 类型别名定义\n\n为了确保状态转换的类型安全，系统使用Python的类型别名（`type`语句）定义每个状态可到达的下一个状态：\n\n```python\ntype BrowsingVideoReachable = Union[BrowsingVideo, ReadingComments]\ntype ReadingCommentsReachable = Union[BrowsingVideo, ReadingComments, PostComment]\ntype PostCommentReachable = Union[BrowsingVideo]\n```\n\n这种设计确保了编译时就能发现无效的状态转换，防止运行时错误。\n\n## 核心类详解\n\n### BilibiliStateBase\n\n`BilibiliStateBase`是所有Bilibili相关状态的抽象基类，它封装了状态机运行所需的所有共享资源和通用逻辑。\n\n```python\nclass BilibiliStateBase(State[None], ABC):\n    model_config = ConfigDict(arbitrary_types_allowed=True)\n    initial_prompt: str\n    memory: Fifo\n    co: Client\n    credential: Credential\n```\n\n**属性说明**：\n\n| 属性名 | 类型 | 用途 |\n|-------|------|------|\n| `initial_prompt` | str | 初始提示词，定义AI的角色和行为准则 |\n| `memory` | Fifo | 先进先出内存，存储历史行为记录 |\n| `co` | Client | Cohere客户端，用于调用大语言模型 |\n| `credential` | Credential | Bilibili API凭证，包含SESSDATA、BILI_JCT、BUVID3 |\n\n**核心方法**：`_infer_state_helper`方法使用LLM来决定下一个状态。当调用此方法时，会向LLM传递当前状态描述、历史行为记录以及可选的下一个状态列表，LLM返回的文本与预定义的选项进行模式匹配，从而决定状态转换的方向。\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:43-58]()\n\n### BrowsingVideo状态\n\n`BrowsingVideo`是系统的入口状态，负责视频搜索和浏览功能。\n\n```python\nclass BrowsingVideo(BilibiliStateBase):\n    @overrides\n    def next(self, signal: None = None) -> BrowsingVideoReachable:\n        # 1. 生成搜索关键词\n        prompt = I(f\"\"\"{self.initial_prompt}...Generate a keyword phrase...\"\"\")\n        response = self.co.chat(temperature=1, message=prompt).text\n        \n        # 2. 调用B站搜索API\n        res = asyncio.run(search.search_by_type(...))\n        self.memory.add(f\"searched for {response}\")\n        \n        # 3. 获取Top10视频供选择\n        top_10 = [...]\n        \n        # 4. 让LLM选择视频\n        video = res['result'][int(response)]\n        self.memory.add(f\"finds {video['title']}\")\n        \n        # 5. 决定下一步\n        return self._infer_state_helper('BrowsingVideo', 'ReadingComments')\n```\n\n该状态的工作流程包括：使用LLM生成创造性的搜索关键词避免重复；调用B站API按粉丝数排序搜索视频；将Top10视频列表展示给LLM供选择；根据`_infer_state_helper`的决策结果决定是继续浏览还是转向评论阅读。\n\n### ReadingComments状态\n\n`ReadingComments`状态专注于视频评论的阅读和选择。当系统处于此状态时，会获取指定视频的热门评论并展示给LLM进行选择。\n\n```python\nclass ReadingComments(BilibiliStateBase):\n    video_bvid: str\n    video_title: str\n    video_description: str\n\n    @overrides\n    def next(self, signal: None = None) -> ReadingCommentsReachable:\n        c = asyncio.run(comment.get_comments(...))\n        top_10 = []\n        for i in range(min(5, c['page']['count'])):\n            cmt = c['replies'][i]\n            top_10.append(f\"{i + 1} {cmt['member']['uname']}: {cmt['content']['message']}\")\n        \n        # 选择评论后决定下一步\n        match self._infer_state_helper('BrowsingVideo', 'ReadingComments', 'PostComment'):\n            case 'BrowsingVideo':\n                return BrowsingVideo(...)\n            case 'ReadingComments':\n                return self\n            case 'PostComment':\n                return PostComment(...)\n```\n\n### PostComment状态\n\n`PostComment`是系统的执行状态，负责生成并发送评论回复。\n\n```python\nclass PostComment(BilibiliStateBase):\n    video_bvid: str\n    video_title: str\n    video_description: str\n    reply_to: str | None\n    reply_to_oid: int | None\n\n    @overrides\n    def next(self, signal: None = None) -> PostCommentReachable:\n        if self.reply_to:\n            prompt = I(f\"\"\"You are replying to a comment: {self.reply_to}...\"\"\")\n            response = self.co.chat(temperature=1, message=prompt).text\n            footnote = f\"\\nI am a bot, contact {os.getenv('name')}...\"\n            \n            # 发送评论\n            asyncio.run(comment.send_comment(...))\n            self.memory.add(f\"commented {response} to {self.video_title}\")\n            \n            # 发布动态\n            asyncio.run(dynamic.send_dynamic(...))\n        \n        return BrowsingVideo(...)\n```\n\n该状态的亮点在于：生成回复后会自动附加免责声明；评论发送成功后会在个人动态中同步发布；无论是否需要回复，都会返回`BrowsingVideo`状态继续新的浏览循环。\n\n## 内存管理系统\n\n### Fifo类设计\n\n`Fifo`（First-In-First-Out）类是一个轻量级的内存管理组件，用于记录AI代理的所有历史行为。\n\n```python\nclass Fifo:\n    def __init__(self):\n        self.capacity = 100\n        self.queue = []\n        self.log_file = \"fifo_log.txt\"\n        if not os.path.exists(self.log_file):\n            with open(self.log_file, 'w') as file:\n                file.write(\"\")\n```\n\n**主要特性**：\n\n| 特性 | 说明 |\n|-----|------|\n| 容量限制 | 最多存储100条记录，超出后自动移除最旧的记录 |\n| 时间戳 | 每条记录都带有精确到秒的时间戳 |\n| 持久化 | 所有操作都会追加写入`fifo_log.txt`日志文件 |\n| 提示生成 | `prompt()`方法返回格式化的历史记录供LLM参考 |\n\n**核心方法**：\n\n```python\ndef add(self, item):\n    if not isinstance(item, str):\n        raise ValueError(\"Only strings can be added to the FIFO\")\n    if len(self.queue) >= self.capacity:\n        self.queue.pop(0)  # 移除最旧的记录\n    timestamp = datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n    self.queue.append((item, timestamp))\n    self.log_to_file(item, timestamp)\n\ndef prompt(self):\n    return \"\\n\".join([f\"{time} - {text}\" for text, time in reversed(self.queue)])\n```\n\n### 内存数据流\n\n```mermaid\ngraph LR\n    A[状态执行] -->|add| B[Fifo队列]\n    B -->|prompt| C[LLM提示词]\n    C -->|决策| D[下一状态]\n    B -->|log_to_file| E[fifo_log.txt]\n```\n\n内存系统在状态转换中扮演着至关重要的角色。每个状态的`next`方法都会调用`memory.add()`记录当前行为，而`_infer_state_helper`方法会调用`memory.prompt()`获取历史记录并包含在LLM提示词中，使AI能够基于过去的决策历史做出更加连贯和智能的选择。\n\n## 执行器机制\n\n### CyclicExecutor工作原理\n\n`CyclicExecutor`是驱动整个状态机运转的核心执行器，采用多线程架构实现状态循环。\n\n```python\nclass CyclicExecutor:\n    def __init__(self, default_time_interval: float):\n        self.running = False\n        self.lock = threading.Lock()\n        self.default_time_interval = default_time_interval\n        self.killed = False\n        self.thread = None\n```\n\n**线程安全设计**：执行器使用`threading.Lock`来保护`running`和`killed`状态标志，确保在多线程环境下状态切换的安全性。`pause()`和`resume()`方法允许在运行时暂停和恢复执行，而`kill()`方法则可以干净地终止整个循环。\n\n### 主循环逻辑\n\n```python\ndef _main_loop(self, state: State) -> None:\n    while True:\n        if self.killed:\n            return\n        \n        if self.running:\n            state = state.next()\n            time.sleep(self.default_time_interval)\n```\n\n主循环采用经典的\"检查-执行-休眠\"模式：每次迭代检查是否被终止或暂停；如果正常运行则调用当前状态的`next()`方法获取下一个状态；然后根据预设的时间间隔进行休眠，控制状态转换的频率。\n\n### 示例启动流程\n\n```python\nif __name__ == \"__main__\":\n    initial_prompt = \"You are a dude browsing Bilibili...\"\n    \n    initial_state = BrowsingVideo(\n        memory=Fifo(),\n        initial_prompt=initial_prompt,\n        co=Client(os.environ.get(\"COHERE_API_KEY\")),\n        credential=Credential(\n            sessdata=SESSDATA,\n            bili_jct=BILI_JCT,\n            buvid3=BUVID3\n        )\n    )\n    executor = CyclicExecutor(5)\n    executor.start(initial_state)\n    time.sleep(1000)\n```\n\n启动时需要准备：FIFO内存实例供状态共享；定义AI角色的初始提示词；配置Bilibili API凭证；创建执行器并传入初始状态。执行器会在后台线程中运行，主线程可以继续执行其他操作或使用`sleep`控制运行时间。\n\n## 环境配置\n\n### 必需的环境变量\n\n系统运行需要配置以下环境变量，通常通过`.env`文件管理：\n\n| 变量名 | 来源 | 用途 |\n|-------|------|------|\n| `COHERE_API_KEY` | Cohere官网 | 调用Cohere大语言模型 |\n| `SESSDATA` | Bilibili网站 | 用户会话认证 |\n| `BILI_JCT` | Bilibili网站 | CSRF令牌 |\n| `BUVID3` | Bilibili网站 | 设备标识 |\n| `name` | 自定义 | 机器人联系信息（用于自动回复的免责声明） |\n\n### 依赖库\n\n```python\nfrom bilibili_api import search, Credential, comment, video, dynamic\nfrom bilibili_api.comment import OrderType, CommentResourceType\nfrom bilibili_api.dynamic import BuildDynamic\nfrom cohere import Client\nfrom overrides import overrides\nfrom pydantic import ConfigDict\n```\n\n主要依赖包括：`bilibili_api`提供B站API封装；`cohere`用于LLM交互；`pydantic`处理数据模型验证；`overrides`确保方法正确重写父类接口。\n\n## 设计模式应用\n\n### 状态设计模式\n\n整个系统建立在GoF的状态设计模式之上。每个具体状态类（如`BrowsingVideo`）都封装了特定状态下的行为和状态转换逻辑，状态之间通过`next()`方法返回下一个状态对象来实现无缝切换。这种设计避免了大型条件语句，使新增状态类型变得简单——只需定义新的状态类并实现`next()`方法即可。\n\n### 工厂模式暗示\n\n虽然代码中没有显式的工厂类，但`next()`方法实际上充当了状态工厂的角色。每个状态根据当前上下文\"生产\"出下一个状态对象，决定系统的后续走向。这种隐式工厂模式与状态模式紧密结合，形成了灵活的状态转换机制。\n\n### 策略模式暗示\n\n`_infer_state_helper`方法可以被视为策略模式的应用。不同的状态可以根据需要传入不同的可选状态列表，LLM的决策策略可以被替换为其他实现（如基于规则的决策），而不影响状态类的整体结构。\n\n## 扩展与定制\n\n### 添加新状态\n\n要添加新的业务状态，需要：\n\n1. 创建新的状态类继承`BilibiliStateBase`\n2. 实现`next()`方法定义状态行为\n3. 定义可达状态类型别名\n4. 在相关状态中添加对该新状态的转换选项\n\n### 替换AI模型\n\n当前使用Cohere作为AI后端，如需替换为其他LLM（如OpenAI GPT），只需：\n\n1. 修改导入语句\n2. 替换`Client`实例化方式\n3. 调整API调用参数（确保参数语义兼容）\n\n### 调整运行参数\n\n| 参数 | 位置 | 说明 |\n|-----|------|------|\n| 状态转换间隔 | `CyclicExecutor(5)` | 5秒，可调整执行频率 |\n| 内存容量 | `Fifo.capacity` | 默认100条记录 |\n| 搜索结果数量 | `range(10)` | 获取Top10视频 |\n| 评论展示数量 | `min(5, ...)` | 显示5条热门评论 |\n\n## 总结\n\nBilibili Surfer示例完整展示了cyclic-agent框架在实际应用中的使用方法。通过有限状态机将复杂的AI行为分解为清晰的状态单元，结合大语言模型实现智能决策，再配合外部API执行实际操作，整个系统能够自主、连续地在Bilibili网站上执行浏览、评论和回复等任务。这个示例不仅是一个可运行的演示程序，更是一个展示AI Agent设计最佳实践的教学案例，为开发者构建自己的AI代理应用提供了完整的参考模板。\n\n---\n\n---\n\n## Doramagic 踩坑日志\n\n项目：xingjianll/cyclic-agent\n\n摘要：发现 6 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：能力坑 - 能力判断依赖假设。\n\n## 1. 能力坑 · 能力判断依赖假设\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：README/documentation is current enough for a first validation pass.\n- 对用户的影响：假设不成立时，用户拿不到承诺的能力。\n- 建议检查：将假设转成下游验证清单。\n- 防护动作：假设必须转成验证项；没有验证结果前不能写成事实。\n- 证据：capability.assumptions | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | README/documentation is current enough for a first validation pass.\n\n## 2. 维护坑 · 维护活跃度未知\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：未记录 last_activity_observed。\n- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。\n- 建议检查：补 GitHub 最近 commit、release、issue/PR 响应信号。\n- 防护动作：维护活跃度未知时，推荐强度不能标为高信任。\n- 证据：evidence.maintainer_signals | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | last_activity_observed missing\n\n## 3. 安全/权限坑 · 下游验证发现风险项\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：no_demo\n- 对用户的影响：下游已经要求复核，不能在页面中弱化。\n- 建议检查：进入安全/权限治理复核队列。\n- 防护动作：下游风险存在时必须保持 review/recommendation 降级。\n- 证据：downstream_validation.risk_items | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | no_demo; severity=medium\n\n## 4. 安全/权限坑 · 存在评分风险\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：no_demo\n- 对用户的影响：风险会影响是否适合普通用户安装。\n- 建议检查：把风险写入边界卡，并确认是否需要人工复核。\n- 防护动作：评分风险必须进入边界卡，不能只作为内部分数。\n- 证据：risks.scoring_risks | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | no_demo; severity=medium\n\n## 5. 维护坑 · issue/PR 响应质量未知\n\n- 严重度：low\n- 证据强度：source_linked\n- 发现：issue_or_pr_quality=unknown。\n- 对用户的影响：用户无法判断遇到问题后是否有人维护。\n- 建议检查：抽样最近 issue/PR，判断是否长期无人处理。\n- 防护动作：issue/PR 响应未知时，必须提示维护风险。\n- 证据：evidence.maintainer_signals | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | issue_or_pr_quality=unknown\n\n## 6. 维护坑 · 发布节奏不明确\n\n- 严重度：low\n- 证据强度：source_linked\n- 发现：release_recency=unknown。\n- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。\n- 建议检查：确认最近 release/tag 和 README 安装命令是否一致。\n- 防护动作：发布节奏未知或过期时，安装说明必须标注可能漂移。\n- 证据：evidence.maintainer_signals | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | release_recency=unknown\n\n<!-- canonical_name: xingjianll/cyclic-agent; human_manual_source: deepwiki_human_wiki -->\n",
      "summary": "DeepWiki/Human Wiki 完整输出，末尾追加 Discovery Agent 踩坑日志。",
      "title": "Human Manual / 人类版说明书"
    },
    "pitfall_log": {
      "asset_id": "pitfall_log",
      "filename": "PITFALL_LOG.md",
      "markdown": "# Pitfall Log / 踩坑日志\n\n项目：xingjianll/cyclic-agent\n\n摘要：发现 6 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：能力坑 - 能力判断依赖假设。\n\n## 1. 能力坑 · 能力判断依赖假设\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：README/documentation is current enough for a first validation pass.\n- 对用户的影响：假设不成立时，用户拿不到承诺的能力。\n- 建议检查：将假设转成下游验证清单。\n- 防护动作：假设必须转成验证项；没有验证结果前不能写成事实。\n- 证据：capability.assumptions | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | README/documentation is current enough for a first validation pass.\n\n## 2. 维护坑 · 维护活跃度未知\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：未记录 last_activity_observed。\n- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。\n- 建议检查：补 GitHub 最近 commit、release、issue/PR 响应信号。\n- 防护动作：维护活跃度未知时，推荐强度不能标为高信任。\n- 证据：evidence.maintainer_signals | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | last_activity_observed missing\n\n## 3. 安全/权限坑 · 下游验证发现风险项\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：no_demo\n- 对用户的影响：下游已经要求复核，不能在页面中弱化。\n- 建议检查：进入安全/权限治理复核队列。\n- 防护动作：下游风险存在时必须保持 review/recommendation 降级。\n- 证据：downstream_validation.risk_items | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | no_demo; severity=medium\n\n## 4. 安全/权限坑 · 存在评分风险\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：no_demo\n- 对用户的影响：风险会影响是否适合普通用户安装。\n- 建议检查：把风险写入边界卡，并确认是否需要人工复核。\n- 防护动作：评分风险必须进入边界卡，不能只作为内部分数。\n- 证据：risks.scoring_risks | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | no_demo; severity=medium\n\n## 5. 维护坑 · issue/PR 响应质量未知\n\n- 严重度：low\n- 证据强度：source_linked\n- 发现：issue_or_pr_quality=unknown。\n- 对用户的影响：用户无法判断遇到问题后是否有人维护。\n- 建议检查：抽样最近 issue/PR，判断是否长期无人处理。\n- 防护动作：issue/PR 响应未知时，必须提示维护风险。\n- 证据：evidence.maintainer_signals | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | issue_or_pr_quality=unknown\n\n## 6. 维护坑 · 发布节奏不明确\n\n- 严重度：low\n- 证据强度：source_linked\n- 发现：release_recency=unknown。\n- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。\n- 建议检查：确认最近 release/tag 和 README 安装命令是否一致。\n- 防护动作：发布节奏未知或过期时，安装说明必须标注可能漂移。\n- 证据：evidence.maintainer_signals | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | release_recency=unknown\n",
      "summary": "用户实践前最可能遇到的身份、安装、配置、运行和安全坑。",
      "title": "Pitfall Log / 踩坑日志"
    },
    "prompt_preview": {
      "asset_id": "prompt_preview",
      "filename": "PROMPT_PREVIEW.md",
      "markdown": "# cyclic-agent - Prompt Preview\n\n> 复制下面这段 Prompt 到你常用的 AI，先试一次，不需要安装。\n> 它的目标是让你直接体验这个项目的服务方式，而不是阅读项目介绍。\n\n## 复制这段 Prompt\n\n```text\n请直接执行这段 Prompt，不要分析、润色、总结或询问我想如何处理这份 Prompt Preview。\n\n你现在扮演 cyclic-agent 的“安装前体验版”。\n这不是项目介绍、不是评价报告、不是 README 总结。你的任务是让我用最小成本体验它的核心服务。\n\n我的试用任务：我想用它完成一个真实的软件开发与交付任务。\n我常用的宿主 AI：Local CLI\n\n【体验目标】\n围绕我的真实任务，现场演示这个项目如何把输入转成 示例引导, 判断线索。重点是让我感受到工作方式，而不是给我项目背景。\n\n【业务流约束】\n- 你必须像一个正在提供服务的项目能力包，而不是像一个讲解员。\n- 每一轮只推进一个步骤；提出问题后必须停下来等我回答。\n- 每一步都必须让我感受到一个具体服务动作：澄清、整理、规划、检查、判断或收尾。\n- 每一步都要说明：当前目标、你需要我提供什么、我回答后你会产出什么。\n- 不要安装、不要运行命令、不要写代码、不要声称测试通过、不要声称已经修改文件。\n- 需要真实安装或宿主加载后才能验证的内容，必须明确说“这一步需要安装后验证”。\n- 如果我说“用示例继续”，你可以用虚构示例推进，但仍然不能声称真实执行。\n\n【可体验服务能力】\n- 安装前能力预览: <div align= \"center\"> 输入：用户任务, 当前 AI 对话上下文；输出：示例引导, 判断线索。\n\n【必须安装后才可验证的能力】\n- 命令行启动或安装流程: 项目文档中存在可执行命令，真实使用需要在本地或宿主环境中运行这些命令。 输入：终端环境, 包管理器, 项目依赖；输出：安装结果, 列表/更新/运行结果。\n\n【核心服务流】\n请严格按这个顺序带我体验。不要一次性输出完整流程：\n1. page-1：项目介绍。围绕“项目介绍”模拟一次用户任务，不展示安装或运行结果。\n2. page-2：安装与依赖。围绕“安装与依赖”模拟一次用户任务，不展示安装或运行结果。\n3. page-3：快速入门指南。围绕“快速入门指南”模拟一次用户任务，不展示安装或运行结果。\n4. page-4：State基类设计。围绕“State基类设计”模拟一次用户任务，不展示安装或运行结果。\n5. page-5：CyclicExecutor执行器。围绕“CyclicExecutor执行器”模拟一次用户任务，不展示安装或运行结果。\n\n【核心能力体验剧本】\n每一步都必须按“输入 -> 服务动作 -> 中间产物”执行。不要只说流程名：\n1. page-1\n输入：用户提供的“项目介绍”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n2. page-2\n输入：用户提供的“安装与依赖”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n3. page-3\n输入：用户提供的“快速入门指南”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n4. page-4\n输入：用户提供的“State基类设计”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n5. page-5\n输入：用户提供的“CyclicExecutor执行器”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n【项目服务规则】\n这些规则决定你如何服务用户。不要解释规则本身，而要在每一步执行时遵守：\n- 先确认用户任务、输入材料和成功标准，再模拟项目能力。\n- 每一步都必须形成可检查的小产物，并等待用户确认后再继续。\n- 凡是需要安装、调用工具或访问外部服务的能力，都必须标记为安装后验证。\n\n【每一步的服务约束】\n- Step 1 / page-1：Step 1 必须围绕“项目介绍”形成一个小中间产物，并等待用户确认。\n- Step 2 / page-2：Step 2 必须围绕“安装与依赖”形成一个小中间产物，并等待用户确认。\n- Step 3 / page-3：Step 3 必须围绕“快速入门指南”形成一个小中间产物，并等待用户确认。\n- Step 4 / page-4：Step 4 必须围绕“State基类设计”形成一个小中间产物，并等待用户确认。\n- Step 5 / page-5：Step 5 必须围绕“CyclicExecutor执行器”形成一个小中间产物，并等待用户确认。\n\n【边界与风险】\n- 不要声称已经安装、运行、调用 API、读写本地文件或完成真实任务。\n- 安装前预览只能展示工作方式，不能证明兼容性、性能或输出质量。\n- 涉及安装、插件加载、工具调用或外部服务的能力必须安装后验证。\n\n【可追溯依据】\n这些路径只用于你内部校验或在我追问“依据是什么”时简要引用。不要在首次回复主动展开：\n- https://github.com/xingjianll/cyclic-agent#readme\n- README.md\n- cyclic_agent/__init__.py\n- pyproject.toml\n- examples/hello_world/hello_world.py\n- cyclic_agent/executor.py\n- cyclic_agent/state.py\n\n【首次问题规则】\n- 首次三问必须先确认用户目标、成功标准和边界，不要提前进入工具、安装或实现细节。\n- 如果后续需要技术条件、文件路径或运行环境，必须等用户确认目标后再追问。\n\n首次回复必须只输出下面 4 个部分：\n1. 体验开始：用 1 句话说明你将带我体验 cyclic-agent 的核心服务。\n2. 当前步骤：明确进入 Step 1，并说明这一步要解决什么。\n3. 你会如何服务我：说明你会先改变我完成任务的哪个动作。\n4. 只问我 3 个问题，然后停下等待回答。\n\n首次回复禁止输出：后续完整流程、证据清单、安装命令、项目评价、营销文案、已经安装或运行的说法。\n\nStep 1 / brainstorming 的二轮协议：\n- 我回答首次三问后，你仍然停留在 Step 1 / brainstorming，不要进入 Step 2。\n- 第二次回复必须产出 6 个部分：澄清后的任务定义、成功标准、边界条件、\n  2-3 个可选方案、每个方案的权衡、推荐方案。\n- 第二次回复最后必须问我是否确认推荐方案；只有我明确确认后，才能进入下一步。\n- 第二次回复禁止输出 git worktree、代码计划、测试文件、命令或真实执行结果。\n\n后续对话规则：\n- 我回答后，你先完成当前步骤的中间产物并等待确认；只有我确认后，才能进入下一步。\n- 每一步都要生成一个小的中间产物，例如澄清后的目标、计划草案、测试意图、验证清单或继续/停止判断。\n- 所有演示都写成“我会建议/我会引导/这一步会形成”，不要写成已经真实执行。\n- 不要声称已经测试通过、文件已修改、命令已运行或结果已产生。\n- 如果某个能力必须安装后验证，请直接说“这一步需要安装后验证”。\n- 如果证据不足，请明确说“证据不足”，不要补事实。\n```\n",
      "summary": "不安装项目也能感受能力节奏的安全试用 Prompt。",
      "title": "Prompt Preview / 安装前试用 Prompt"
    },
    "quick_start": {
      "asset_id": "quick_start",
      "filename": "QUICK_START.md",
      "markdown": "# Quick Start / 官方入口\n\n项目：xingjianll/cyclic-agent\n\n## 官方安装入口\n\n### Python / pip · 官方安装入口\n\n```bash\npip install cyclic-agent\n```\n\n来源：https://github.com/xingjianll/cyclic-agent#readme\n\n## 来源\n\n- docs: https://github.com/xingjianll/cyclic-agent#readme\n",
      "summary": "从项目官方 README 或安装文档提取的开工入口。",
      "title": "Quick Start / 官方入口"
    }
  },
  "validation_id": "dval_5d1a5684881840c7a9f8cecb96cb914a"
}
