{
  "canonical_name": "xingjianll/cyclic-agent",
  "compilation_id": "pack_eacdf2cd151d440b900528326d7686f2",
  "created_at": "2026-05-24T13:31:16.302934+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": "Knowledge Retrieval",
        "label_zh": "知识检索",
        "source": "repo_evidence_project_characteristics",
        "tag_id": "product_domain-knowledge-retrieval",
        "type": "product_domain"
      },
      {
        "label_en": "Knowledge Base Q&A",
        "label_zh": "知识库问答",
        "source": "repo_evidence_project_characteristics",
        "tag_id": "user_job-knowledge-base-q-a",
        "type": "user_job"
      },
      {
        "label_en": "Structured Data Extraction",
        "label_zh": "结构化数据提取",
        "source": "repo_evidence_project_characteristics",
        "tag_id": "core_capability-structured-data-extraction",
        "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": "Open Source Tool",
        "label_zh": "开源工具",
        "source": "repo_evidence_project_characteristics",
        "tag_id": "selection_signal-open-source-tool",
        "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> Copy the prompt below into your AI host before installing anything.\n> Its purpose is to let you safely feel the project's workflow, not to claim the project has already run.\n\n## Copy this prompt\n\n```text\nYou are using an independent Doramagic capability pack for xingjianll/cyclic-agent.\n\nProject:\n- Name: cyclic-agent\n- Repository: https://github.com/xingjianll/cyclic-agent\n- Summary: <div align= \"center\">\n- Host target: local_cli\n\nGoal:\nHelp me evaluate this project for the following task without installing it yet: <div align= \"center\">\n\nBefore taking action:\n1. Restate my task, success standard, and boundary.\n2. Identify whether the next step requires tools, browser access, network access, filesystem access, credentials, package installation, or host configuration.\n3. Use only the Doramagic Project Pack, the upstream repository, and the source-linked evidence listed below.\n4. If a real command, install step, API call, file write, or host integration is required, mark it as \"requires post-install verification\" and ask for approval first.\n5. If evidence is missing, say \"evidence is missing\" instead of filling the gap.\n\nPreviewable capabilities:\n- Capability 1: <div align= \"center\">\n\nCapabilities that require post-install verification:\n- Capability 1: Use the source-backed project context to guide one small, checkable workflow step.\n\nCore service flow:\n1. page-1: Installation and Setup. Produce one small intermediate artifact and wait for confirmation.\n2. page-2: Project Overview. Produce one small intermediate artifact and wait for confirmation.\n3. page-3: State Base Class. Produce one small intermediate artifact and wait for confirmation.\n4. page-4: CyclicExecutor. Produce one small intermediate artifact and wait for confirmation.\n5. page-5: System Architecture. Produce one small intermediate artifact and wait for confirmation.\n\nSource-backed evidence to keep in mind:\n- https://github.com/xingjianll/cyclic-agent#readme\n- pyproject.toml\n- README.md\n- cyclic_agent/state.py\n- cyclic_agent/__init__.py\n- cyclic_agent/executor.py\n- examples/bilibili_surfer/bilibili_surfer.py\n\nFirst response rules:\n1. Start Step 1 only.\n2. Explain the one service action you will perform first.\n3. Ask exactly three questions about my target workflow, success standard, and sandbox boundary.\n4. Stop and wait for my answers.\n\nStep 1 follow-up protocol:\n- After I answer the first three questions, stay in Step 1.\n- Produce six parts only: clarified task, success standard, boundary conditions, two or three options, tradeoffs for each option, and one recommendation.\n- End by asking whether I confirm the recommendation.\n- Do not move to Step 2 until I explicitly confirm.\n\nConversation rules:\n- Advance one step at a time and wait for confirmation after each small artifact.\n- Write outputs as recommendations or planned checks, not as completed execution.\n- Do not claim tests passed, files changed, commands ran, APIs were called, or the project was installed.\n- If the user asks for execution, first provide the sandbox setup, expected output, rollback, and approval checkpoint.\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 06:16:55 UTC\n\n## 目录\n\n- [Installation and Setup](#page-1)\n- [Project Overview](#page-2)\n- [State Base Class](#page-3)\n- [CyclicExecutor](#page-4)\n- [System Architecture](#page-5)\n- [Creating Custom States](#page-6)\n- [Memory Management with Fifo](#page-7)\n- [Hello World Example](#page-8)\n- [Bilibili Surfer Example](#page-9)\n- [Helper States](#page-10)\n\n<a id='page-1'></a>\n\n## Installation and Setup\n\n### 相关页面\n\n相关主题：[State Base Class](#page-3), [Hello World Example](#page-8)\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- [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# Installation and Setup\n\n## Overview\n\nCyclicAgent is a framework for creating LLM-powered, fully-autonomous AI agents using a finite state machine (FSM) architecture. The framework abstracts an agent as a collection of states that implement transition functions, allowing for cyclic execution patterns.\n\n资料来源：[README.md:1-8]()\n\n## Prerequisites\n\nBefore installing CyclicAgent, ensure your environment meets the following requirements:\n\n| Requirement | Minimum Version | Notes |\n|-------------|-----------------|-------|\n| Python | 3.10+ | Required for Pydantic v2 features |\n| pip | Latest recommended | For package installation |\n| LLM API Key | Provider-specific | Cohere, OpenAI, or similar |\n\n### Required Dependencies\n\nThe core dependencies include:\n\n- **Pydantic** - Base model and type validation\n- **Cohere SDK** or **OpenAI SDK** - For LLM integration\n- **python-dotenv** - For environment variable management\n\n资料来源：[cyclic_agent/state.py:1-4]()\n\n## Installation Methods\n\n### Standard Installation (Recommended)\n\nInstall the package directly from PyPI:\n\n```bash\npip install cyclic-agent\n```\n\n资料来源：[README.md:7-9]()\n\n### Development Installation\n\nFor contributing or modifying the source code:\n\n```bash\ngit clone https://github.com/xingjianll/cyclic-agent.git\ncd cyclic-agent\npip install -e .\n```\n\n### Dependencies in pyproject.toml\n\nThe package configuration specifies core dependencies for state management and LLM integration.\n\n资料来源：[pyproject.toml](https://github.com/xingjianll/cyclic-agent/blob/main/pyproject.toml)\n\n## Project Configuration\n\n### Environment Variables Setup\n\nCreate a `.env` file in your project root to store sensitive credentials:\n\n```bash\nCOHERE_API_KEY=your_api_key_here\n```\n\n#### Example .env Configuration\n\n```bash\n# LLM Configuration\nCOHERE_API_KEY=your_cohere_api_key\n\n# Platform-specific (for Bilibili example)\nSESSDATA=your_bilibili_sessdata\nBILI_JCT=your_bilibili_jct\nBUVID3=your_bilibili_buvid3\nNAME=your_name_for_bot_footers\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:1-20]()\n\n## Core Package Imports\n\nAfter installation, import the essential components:\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\n```\n\n资料来源：[cyclic_agent/__init__.py:1-6]()\n\n### Available Exports\n\n| Symbol | Type | Description |\n|--------|------|-------------|\n| `State` | Class | Abstract base class for all agent states |\n| `CyclicExecutor` | Class | Execution engine for running the state machine |\n\n## State Machine Architecture\n\nThe framework uses a state design pattern where each state implements a `next()` method returning the subsequent state.\n\n```mermaid\ngraph TD\n    A[Initial State] -->|next()| B[State 1]\n    B -->|next()| C[State 2]\n    C -->|next()| D[State N]\n    D -->|next()| A\n```\n\n资料来源：[README.md:10-16]()\n\n## Creating Your First Agent\n\n### Basic Setup Pattern\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\n资料来源：[examples/hello_world/hello_world.py:1-16]()\n\n### Implementing States\n\nEach state must inherit from `State` and implement the `next()` method:\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资料来源：[examples/hello_world/hello_world.py:18-24]()\n\n### State Base Class Requirements\n\nThe `State` class is a Pydantic `BaseModel` with an abstract method:\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-12]()\n\n## Running the Executor\n\n### Basic Execution\n\n```python\nif __name__ == \"__main__\":\n    initial_state = AskQuestion()\n    executor = CyclicExecutor(5)  # 5-second interval\n    executor.start(initial_state)\n    time.sleep(20)\n```\n\n资料来源：[examples/hello_world/hello_world.py:34-40]()\n\n### Executor Configuration\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `default_time_interval` | `float` | Required | Seconds between state transitions |\n| `running` | `bool` | `False` | Execution status |\n| `killed` | `bool` | `False` | Termination flag |\n\n资料来源：[cyclic_agent/executor.py:4-10]()\n\n### Executor Control Methods\n\n```mermaid\ngraph LR\n    A[start] --> B[running=True]\n    B --> C[_main_loop]\n    C --> D{state.next}\n    D --> E[time.sleep]\n    E --> C\n    F[pause] --> G[running=False]\n    H[resume] --> B\n    I[kill] --> J[killed=True]\n    J --> K[thread.join]\n```\n\nThe `CyclicExecutor` class provides thread-safe control:\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    def 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资料来源：[cyclic_agent/executor.py:4-25]()\n\n## Advanced Setup: Memory Integration\n\nFor agents requiring persistent memory, extend the base state class:\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:28-35]()\n\n### Memory Class Implementation\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\n资料来源：[examples/bilibili_surfer/fifo.py:1-14]()\n\n## Complete Project Structure\n\n```\ncyclic-agent/\n├── cyclic_agent/\n│   ├── __init__.py      # Package exports: State, CyclicExecutor\n│   ├── state.py         # State base class definition\n│   ├── executor.py      # CyclicExecutor implementation\n│   ├── cot.py           # Chain-of-thought state\n│   └── search.py        # Search state interface\n├── examples/\n│   ├── hello_world/     # Basic agent example\n│   └── bilibili_surfer/  # Complex multi-state example\n└── pyproject.toml       # Package configuration\n```\n\n## Verification Checklist\n\n- [ ] Python 3.10+ installed\n- [ ] `pip install cyclic-agent` completed successfully\n- [ ] `.env` file created with required API keys\n- [ ] `from cyclic_agent import State, CyclicExecutor` imports without errors\n- [ ] Basic state class compiles correctly\n- [ ] Executor starts without exceptions\n\n## Troubleshooting Common Setup Issues\n\n| Issue | Solution |\n|-------|----------|\n| ImportError for State | Ensure `from __future__ import annotations` is present |\n| Type validation errors | Use `model_config = ConfigDict(arbitrary_types_allowed=True)` |\n| Threading issues | Executor methods are thread-safe via locks |\n| Forward reference errors | Use `from __future__ import annotations` at file top |\n\n资料来源：[cyclic_agent/state.py:1-2](), [examples/bilibili_surfer/bilibili_surfer.py:30]()\n\n---\n\n<a id='page-2'></a>\n\n## Project Overview\n\n### 相关页面\n\n相关主题：[State Base Class](#page-3), [CyclicExecutor](#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/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/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- [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- [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</details>\n\n# Project Overview\n\n## Introduction\n\nCyclicAgent is a Python framework designed for creating **LLM-powered, fully-autonomous AI agents**. It provides a clean abstraction for building AI systems that can continuously operate by modeling agent behavior as a finite state machine (FSM). 资料来源：[README.md:1]()\n\nThe framework enables developers to define AI behavior through a state design pattern, where each state represents a distinct behavior or action the agent can perform. States transition to one another based on internal attributes (such as memory and meta prompts) as well as external signals, creating a cyclic execution model that can run indefinitely. 资料来源：[README.md:6-9]()\n\n## Core Design Philosophy\n\nCyclicAgent abstracts an agent as a **finite state machine (FSM)** using the state design pattern. This approach offers several advantages:\n\n| Benefit | Description |\n|---------|-------------|\n| **Modularity** | Each behavior is encapsulated in its own state class |\n| **Scalability** | New states can be added without modifying existing ones |\n| **Predictability** | State transitions follow defined rules |\n| **Testability** | Individual states can be tested in isolation |\n| **Extensibility** | The framework supports custom state types and transitions |\n\n资料来源：[README.md:6-9]()\n\n### State Transition Model\n\nThe fundamental principle of CyclicAgent is that **all states implement a state transition function**, which returns another state. This allows for chaining transition operations indefinitely, making the agent \"Cyclic\". 资料来源：[README.md:10-11]()\n\n```mermaid\ngraph TD\n    A[Initial State] -->|next()| B[State 1]\n    B -->|next()| C[State 2]\n    C -->|next()| D[State 3]\n    D -->|next()| B\n    E[External Signal] -.->|signal| C\n```\n\n## Architecture\n\n### System Components\n\nCyclicAgent consists of the following core components:\n\n| Component | File | Purpose |\n|-----------|------|---------|\n| `State` | `cyclic_agent/state.py` | Abstract base class for all agent states |\n| `CyclicExecutor` | `cyclic_agent/executor.py` | Manages the execution loop of states |\n| `Search` | `cyclic_agent/search.py` | Specialized state for search operations |\n| `CoT` | `cyclic_agent/cot.py` | Chain-of-thought reasoning state |\n\n资料来源：[cyclic_agent/__init__.py:1-6]()\n\n### Class Hierarchy\n\n```mermaid\nclassDiagram\n    class State~SigT~ {\n        <<abstract>>\n        +next(signal) State\n    }\n    class CyclicExecutor {\n        -running: bool\n        -default_time_interval: float\n        +start(initial_state)\n        +pause()\n        +resume()\n        +kill()\n    }\n    class Search {\n        +query: str\n        +exit_: Callable\n        +search(query) str\n    }\n    class CoT {\n        +exit_: Callable\n        +llm: State\n        +prompt: str\n    }\n    State <|-- Search\n    State <|-- CoT\n```\n\n## Core Components\n\n### State Base Class\n\nThe `State` class is the foundation of the framework. It is a **generic abstract base class** built on Pydantic's `BaseModel`, providing type safety and data validation. 资料来源：[cyclic_agent/state.py:1-13]()\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**Key Features:**\n- **Generic Type Parameter**: `SigT` represents the signal type for state transitions\n- **Pydantic Integration**: Enables automatic data validation and serialization\n- **Abstract Method**: `next()` must be implemented by all concrete states\n\n资料来源：[cyclic_agent/state.py:1-13]()\n\n### CyclicExecutor\n\nThe `CyclicExecutor` is responsible for running the state machine in a separate thread. It manages the execution lifecycle including start, pause, resume, and kill operations. 资料来源：[cyclic_agent/executor.py:1-45]()\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| Parameter | Type | Description |\n|-----------|------|-------------|\n| `default_time_interval` | `float` | Sleep duration (seconds) between state transitions |\n| `running` | `bool` | Flag indicating if executor is actively running |\n| `killed` | `bool` | Flag indicating if executor has been terminated |\n\n**Execution Flow:**\n\n```mermaid\ngraph TD\n    A[Start] --> B{running?}\n    B -->|Yes| C[state = state.next()]\n    B -->|No| D[Wait]\n    C --> E[Sleep for interval]\n    E --> B\n    D --> B\n    F[Kill Signal] --> G[killed = True]\n    G --> H[Exit Loop]\n```\n\n资料来源：[cyclic_agent/executor.py:1-45]()\n\n## State Implementation Patterns\n\n### Simple State Pattern\n\nStates are implemented by extending the `State` class and implementing the `next()` method. Each state returns the next state to transition to. 资料来源：[examples/hello_world/hello_world.py:1-38]()\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```\n\n**Transition Diagram:**\n\n```mermaid\ngraph LR\n    A[AskQuestion] -->|next()| B[AnswerQuestion]\n    B -->|next()| A\n```\n\n### State with Memory Pattern\n\nAdvanced states can maintain memory to track past actions and decisions. The Bilibili Surfer example demonstrates this pattern using a FIFO (First-In-First-Out) queue. 资料来源：[examples/bilibili_surfer/fifo.py:1-27]()\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| Attribute | Type | Purpose |\n|-----------|------|---------|\n| `initial_prompt` | `str` | Base prompt for LLM interactions |\n| `memory` | `Fifo` | Queue storing past agent actions |\n| `co` | `Client` | Cohere LLM client instance |\n| `credential` | `Credential` | Authentication credentials |\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:1-55]()\n\n### State Inference Pattern\n\nStates can use LLM-driven inference to determine the next state dynamically:\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资料来源：[examples/bilibili_surfer/bilibili_surfer.py:28-43]()\n\n## Memory System\n\n### FIFO Queue Implementation\n\nThe framework includes a `Fifo` class for maintaining conversation history and action logs:\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| Feature | Description |\n|---------|-------------|\n| `capacity` | Maximum number of items (default: 100) |\n| `queue` | List storing items with timestamps |\n| `log_file` | Persistent log file for audit trail |\n\n**Behavior:**\n- When capacity is reached, the oldest item is automatically removed\n- Each item is timestamped and logged to file\n- The `prompt()` method returns items in reverse chronological order\n\n资料来源：[examples/bilibili_surfer/fifo.py:1-27]()\n\n## Specialized States\n\n### Search State\n\nA generic search state that executes queries and transitions based on results:\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-14]()\n\n### Chain-of-Thought State\n\nEnables step-by-step reasoning by appending \"Let's think step by step.\" to prompts:\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        return self.llm(prompt=prompt, callback=self.exit_)\n```\n\n资料来源：[cyclic_agent/cot.py:1-15]()\n\n## Complete Workflow Example\n\nThe Bilibili Surfer demonstrates a complete autonomous agent workflow:\n\n```mermaid\ngraph TD\n    A[BrowsingVideo] -->|search videos| B[Display Top 10 Videos]\n    B --> C{Select Video}\n    C -->|browse| D[ReadingComments]\n    D -->|view comments| E{Choose Action}\n    E -->|reply| F[PostComment]\n    E -->|continue| D\n    F -->|done| A\n    D -->|back| A\n```\n\n**State Transitions:**\n\n| Current State | Next State(s) | Trigger |\n|---------------|---------------|---------|\n| `BrowsingVideo` | `BrowsingVideo`, `ReadingComments` | LLM inference |\n| `ReadingComments` | `BrowsingVideo`, `ReadingComments`, `PostComment` | LLM inference |\n| `PostComment` | `BrowsingVideo` | Comment posted |\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:1-180]()\n\n## Package Exports\n\nThe framework exposes a minimal public API:\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\n```\n\nAll core functionality is accessible through these two classes, keeping the API simple and intuitive for developers. 资料来源：[cyclic_agent/__init__.py:1-6]()\n\n## Installation\n\nInstall the framework via pip:\n\n```shell\npip install cyclic-agent\n```\n\nThe package is available on PyPI and can be integrated into any Python project. 资料来源：[README.md:4-6]()\n\n## Requirements\n\n- Python 3.10+ (for generic syntax support)\n- Pydantic for data validation\n- `from __future__ import annotations` may be needed for forward references in some Python versions 资料来源：[README.md:28]()\n\n## Summary\n\nCyclicAgent provides a clean, Pythonic way to build autonomous AI agents using the finite state machine pattern. Its key strengths include:\n\n1. **Simple Core API**: Only two main classes (`State` and `CyclicExecutor`) needed for basic usage\n2. **Flexible State Definition**: States are Pydantic models with type safety\n3. **Memory Integration**: Built-in support for FIFO queues and action logging\n4. **Thread-Safe Execution**: Concurrent execution with pause/resume/kill controls\n5. **Extensible Design**: Custom state types can be created by extending the base class\n\nThe framework is well-suited for building autonomous agents that need to make decisions, maintain context, and perform actions in a continuous loop.\n\n---\n\n<a id='page-3'></a>\n\n## State Base Class\n\n### 相关页面\n\n相关主题：[CyclicExecutor](#page-4), [Creating Custom States](#page-6)\n\n<details>\n<summary>Relevant Source Files</summary>\n\n以下源码文件用于生成本页说明：\n\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/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 Base Class\n\n## Overview\n\nThe `State` class is the foundational abstraction in CyclicAgent, implementing the **State Design Pattern** to model agents as finite state machines (FSM). Every agent behavior is encapsulated as a state that can transition to another state through the `next()` method.\n\n**Core Design Principle:** States implement a transition function that returns another state, enabling indefinite chaining and creating the \"cyclic\" nature of the agent framework.\n\n资料来源：[cyclic_agent/state.py:6-9]()\n\n---\n\n## Architecture\n\n### Class Definition\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| Property | Description |\n|----------|-------------|\n| Generic Parameter `SigT` | Signal type for external communication between states |\n| Base Class | Pydantic `BaseModel` for data validation and serialization |\n| Abstract Method `next()` | Must be implemented by subclasses to define state transitions |\n\n资料来源：[cyclic_agent/state.py:6-9]()\n\n### Generic Type Parameter `SigT`\n\nThe `SigT` generic parameter defines the type of signal an external entity can send to influence state transitions:\n\n| Signal Type | Use Case |\n|-------------|----------|\n| `State[None]` | Autonomous states with no external input |\n| `State[str]` | States that receive string-based signals |\n| `State[Any]` | States accepting any signal type |\n\n资料来源：[cyclic_agent/state.py:6]()\n\n### Relationship with CyclicExecutor\n\n```mermaid\ngraph TD\n    A[Initial State] -->|next()| B[State B]\n    B -->|next()| C[State C]\n    C -->|next()| A\n    D[CyclicExecutor] -->|controls| E[Running Loop]\n    E -->|calls next()| A\n    E -->|calls next()| B\n    E -->|calls next()| C\n```\n\nThe `CyclicExecutor` runs a continuous loop that repeatedly calls `next()` on the current state, enabling cyclic transitions.\n\n资料来源：[cyclic_agent/executor.py:28-33]()\n\n---\n\n## Implementation Patterns\n\n### Pattern 1: Simple Two-State Cyclic Agent\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\nimport cohere\n\nclass AskQuestion(State[None]):\n    def next(self, signal: None = None) -> AnswerQuestion:\n        response = cohere.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 = cohere.chat(message=self.question)\n        return AskQuestion()\n```\n\n资料来源：[examples/hello_world/hello_world.py:10-24]()\n\n### Pattern 2: State with Context Attributes\n\nStates inherit from `BaseModel`, allowing Pydantic field definitions for context:\n\n```python\nclass AnswerQuestion(State[None]):\n    question: str  # Context attribute persisted across transitions\n\n    def next(self, signal: None = None) -> AskQuestion:\n        answer = cohere.chat(message=self.question)\n        return AskQuestion()\n```\n\n资料来源：[examples/hello_world/hello_world.py:19-24]()\n\n### Pattern 3: Complex State with Type Unions\n\nDefine reachable states using Python type unions for type-safe transitions:\n\n```python\ntype BrowsingVideoReachable = Union[BrowsingVideo, ReadingComments]\n\n\nclass BrowsingVideo(BilibiliStateBase):\n    @overrides\n    def next(self, signal: None = None) -> BrowsingVideoReachable:\n        # ... logic ...\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资料来源：[examples/bilibili_surfer/bilibili_surfer.py:1-85]()\n\n---\n\n## State Machine Design\n\n### Transition Flow\n\n```mermaid\ngraph LR\n    S1[State 1] -->|next() returns State 2| S2[State 2]\n    S2 -->|next() returns State 3| S3[State 3]\n    S3 -->|next() returns State 1| S1\n```\n\nEach state transition:\n1. Receives optional `signal` parameter\n2. Executes state-specific logic\n3. Returns the next state instance\n4. Context (fields) can be preserved or replaced\n\n### Base Class Requirements\n\n| Requirement | Implementation |\n|-------------|----------------|\n| Inherit from `State[SigT]` | Provides FSM contract |\n| Implement `next()` | Defines transition logic |\n| Use `from __future__ import annotations` | Required for forward references |\n\n资料来源：[examples/hello_world/hello_world.py:1-3]()\n\n---\n\n## Advanced Usage: Abstract Base State\n\nFor complex applications, create an abstract base state with shared functionality:\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        \"\"\"Helper method for LLM-driven state inference.\"\"\"\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            \"\"\"\n        )\n        return self.co.chat(temperature=1, message=prompt).text\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:25-40]()\n\n---\n\n## Integration with CyclicExecutor\n\n| Executor Method | State Interaction |\n|-----------------|-------------------|\n| `start(initial_state)` | Begins execution with starting state |\n| `_main_loop(state)` | Calls `state.next()` in loop |\n| `pause()` / `resume()` | Controls execution flow |\n| `kill()` | Stops execution permanently |\n\n```python\nclass CyclicExecutor:\n    def _main_loop(self, state: State) -> None:\n        while True:\n            if self.killed:\n                return\n            if self.running:\n                state = state.next()  # State transition\n                time.sleep(self.default_time_interval)\n```\n\n资料来源：[cyclic_agent/executor.py:28-33]()\n\n---\n\n## Export and Import\n\nThe `State` class is exported from the package root:\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\n```\n\n资料来源：[cyclic_agent/__init__.py:1-4]()\n\n---\n\n## Summary\n\n| Aspect | Description |\n|--------|-------------|\n| **Purpose** | Base class for all agent states in FSM architecture |\n| **Base** | Pydantic `BaseModel` |\n| **Generic** | `State[SigT]` for signal type parameterization |\n| **Key Method** | `next(signal)` returns next state |\n| **Usage** | Inherit and implement `next()` for state behavior |\n\n---\n\n<a id='page-4'></a>\n\n## CyclicExecutor\n\n### 相关页面\n\n相关主题：[State Base Class](#page-3), [Creating Custom States](#page-6), [Helper States](#page-10)\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- [README.md](https://github.com/xingjianll/cyclic-agent/blob/main/README.md)\n</details>\n\n# CyclicExecutor\n\n## Overview\n\nCyclicExecutor is the core execution engine in the CyclicAgent framework. It manages the continuous execution loop that drives the finite state machine (FSM) pattern implemented by agents. The executor handles state transitions, threading, and timing control for autonomous agent behavior.\n\n**Purpose:** The CyclicExecutor provides a runtime environment for executing state machines where each state can transition to another state indefinitely, enabling fully autonomous AI agents.\n\n**Scope:** It abstracts away the complexity of thread management, timing, and execution flow, allowing developers to focus purely on defining state behavior.\n\n资料来源：[cyclic_agent/executor.py:1-34]()\n\n## Architecture\n\n### Design Pattern\n\nCyclicExecutor implements the **State Design Pattern** where agents are represented as finite state machines. Each state implements a `next()` method that returns the subsequent state, creating an unbounded chain of transitions.\n\n```mermaid\ngraph TD\n    A[Initial State] -->|next()| B[State 1]\n    B -->|next()| C[State 2]\n    C -->|next()| D[State N]\n    D -->|next()| A\n    D -->|next()| B\n```\n\n### Class Structure\n\n| Component | Type | Description |\n|-----------|------|-------------|\n| `running` | `bool` | Flag indicating if executor is active |\n| `killed` | `bool` | Flag indicating permanent shutdown |\n| `lock` | `threading.Lock` | Thread synchronization primitive |\n| `thread` | `threading.Thread` | Background execution thread |\n| `default_time_interval` | `float` | Sleep duration between state transitions |\n\n资料来源：[cyclic_agent/executor.py:7-14]()\n\n## API Reference\n\n### Constructor\n\n```python\ndef __init__(self, default_time_interval: float)\n```\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `default_time_interval` | `float` | required | Seconds to sleep between each state transition |\n\n### Methods\n\n#### `start(initial_state: State) -> None`\n\nInitiates the executor in a new background thread. The executor begins calling `state.next()` repeatedly, transitioning through states at intervals defined by `default_time_interval`.\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `initial_state` | `State[SigT]` | The starting state of the FSM |\n\n```python\nexecutor = CyclicExecutor(5)\nexecutor.start(initial_state)\n```\n\n#### `pause() -> None`\n\nTemporarily halts execution without terminating the thread. The thread remains alive but the main loop skips state transitions.\n\n#### `resume() -> None`\n\nResumes execution after a pause. State transitions continue from the current state.\n\n#### `kill() -> None`\n\nPermanently stops the executor and joins the thread. Sets `killed` flag to `True` ensuring the main loop terminates cleanly.\n\n```python\nexecutor.kill()  # Clean shutdown\n```\n\n资料来源：[cyclic_agent/executor.py:16-31]()\n\n## Execution Flow\n\n### Main Loop Logic\n\n```mermaid\nflowchart TD\n    A[_main_loop started] --> B{killed?}\n    B -->|Yes| Z[Return]\n    B -->|No| C{running?}\n    C -->|No| D[Sleep default_time_interval]\n    D --> B\n    C -->|Yes| E[state = state.next()]\n    E --> F[Sleep default_time_interval]\n    F --> B\n```\n\nThe `_main_loop` method runs in a dedicated thread and performs the following operations:\n\n1. Check `killed` flag; exit if `True`\n2. Check `running` flag; skip transition if `False`\n3. Call `state.next()` to get the next state\n4. Sleep for `default_time_interval` seconds\n5. Repeat\n\n资料来源：[cyclic_agent/executor.py:33-35]()\n\n### Thread Safety\n\nThe executor uses a `threading.Lock` to protect shared state modifications:\n\n```python\nself.lock = threading.Lock()\n\ndef pause(self):\n    with self.lock:\n        self.running = False\n```\n\nAll state modifications (`start`, `pause`, `resume`, `kill`) acquire the lock before modifying `running` or `killed` flags.\n\n资料来源：[cyclic_agent/executor.py:10]()\n\n## State Integration\n\n### State Base Class\n\nThe executor expects states to implement the `State[SigT]` protocol:\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\nStates are Pydantic models, enabling automatic serialization and validation of state data.\n\n资料来源：[cyclic_agent/state.py:6-9]()\n\n### Type Parameter Usage\n\nThe generic type `SigT` allows states to receive external signals of any type:\n\n| Type Parameter | Signal Type | Usage |\n|----------------|--------------|-------|\n| `State[None]` | No signal | Simple autonomous agents |\n| `State[str]` | String messages | Interactive agents |\n| `State[dict]` | Structured data | Data-driven agents |\n\n资料来源：[cyclic_agent/state.py:6]()\n\n## Configuration Options\n\n| Option | Value Type | Default | Effect |\n|--------|------------|---------|--------|\n| `default_time_interval` | `float` | Required | Controls execution speed; lower = faster transitions |\n| Thread spawning | Automatic | - | Creates daemon thread on `start()` |\n| Signal handling | Passive | - | No signal handling implemented |\n\n### Interval Selection Guidelines\n\n| Interval Range | Use Case |\n|----------------|----------|\n| `0.1 - 1.0` | Fast response scenarios, API polling |\n| `1.0 - 5.0` | Balanced interaction, LLM response times |\n| `5.0 - 60.0` | Slow operations, external API rate limits |\n\n资料来源：[cyclic_agent/executor.py:12]()\n\n## Usage Examples\n\n### Basic Hello World\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\", temperature=1)\n        return AnswerQuestion(question=response.text)\n\nclass AnswerQuestion(State[None]):\n    question: str\n    \n    def next(self, signal=None) -> AskQuestion:\n        answer = co.chat(message=self.question)\n        return AskQuestion()\n\n# Initialize and run\nexecutor = CyclicExecutor(5)  # 5-second intervals\nexecutor.start(AskQuestion())\ntime.sleep(20)\nexecutor.kill()\n```\n\n资料来源：[examples/hello_world/hello_world.py:1-26]()\n\n### Complex Agent: Bilibili Surfer\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\n\nclass BrowsingVideo(BilibiliStateBase):\n    @overrides\n    def next(self, signal=None) -> BrowsingVideoReachable:\n        # Search and select video\n        response = self.co.chat(temperature=1, message=prompt).text\n        video = res['result'][int(response)]\n        \n        # Return next state based on decision\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资料来源：[examples/bilibili_surfer/bilibili_surfer.py:1-95]()\n\n### Typical Execution Pattern\n\n```mermaid\nsequenceDiagram\n    participant Main as Main Thread\n    participant Executor as CyclicExecutor\n    participant State as Current State\n    \n    Main->>Executor: start(initial_state)\n    Executor->>Executor: Create Thread\n    \n    loop Every default_time_interval seconds\n        Executor->>State: state.next()\n        State-->>Executor: Next State\n        Executor->>State: Update state reference\n    end\n    \n    Main->>Executor: kill()\n    Executor->>Executor: Set killed=True\n    Executor->>Main: Thread joins\n```\n\n## Exports\n\nCyclicExecutor is exported from the main package:\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\n```\n\n```python\n__all__ = [\"State\", \"CyclicExecutor\"]\n```\n\n资料来源：[cyclic_agent/__init__.py:1-6]()\n\n## Limitations\n\n- **Daemon Thread:** The execution thread is a daemon thread, meaning it won't prevent the Python process from exiting\n- **No Signal Handling:** External signals cannot interrupt the execution loop\n- **No State Persistence:** States are not persisted between sessions\n- **Single Thread:** Only one thread executes states; no parallel state machines\n\n资料来源：[cyclic_agent/executor.py:18]()\n\n## Related Components\n\n| Component | File | Relationship |\n|-----------|------|--------------|\n| `State` | `cyclic_agent/state.py` | Base class for states |\n| `Search` | `cyclic_agent/search.py` | Generic search state |\n| `CoT` | `cyclic_agent/cot.py` | Chain-of-thought state |\n| `Fifo` | `examples/bilibili_surfer/fifo.py` | Memory for states |\n\n资料来源：[cyclic_agent/search.py:1-14](), [cyclic_agent/cot.py:1-18](), [examples/bilibili_surfer/fifo.py:1-30]()\n\n---\n\n<a id='page-5'></a>\n\n## System Architecture\n\n### 相关页面\n\n相关主题：[State Base Class](#page-3), [CyclicExecutor](#page-4), [Memory Management with Fifo](#page-7)\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/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# System Architecture\n\n## Overview\n\nCyclicAgent is a framework for building autonomous AI agents based on the **Finite State Machine (FSM)** design pattern. The architecture abstracts an agent as a collection of states, where each state implements a transition function that returns another state, enabling cyclic execution flows. 资料来源：[README.md:9]()\n\nThe system is designed to handle autonomous workflows where agents can:\n\n- Maintain internal state (memory, prompts)\n- Respond to external signals\n- Transition between states infinitely\n- Interact with external environments (APIs, platforms)\n\n## Core Design Principles\n\n### State Pattern Implementation\n\nThe architecture uses Python's generic type syntax (PEP 695) combined with Pydantic for state modeling. Each state is a Pydantic model that encapsulates both data and behavior. 资料来源：[cyclic_agent/state.py:8]()\n\n### Key Characteristics\n\n| Characteristic | Description |\n|----------------|-------------|\n| **Type Safety** | Generic type parameters enable compile-time checking |\n| **Serialization** | Pydantic BaseModel provides automatic serialization |\n| **Extensibility** | Abstract base allows custom state implementations |\n| **Thread Safety** | Executor uses locks for safe concurrent operation |\n\n## Architecture Components\n\n### State Base Class\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\nThe `State` class serves as the foundation for all agent states:\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `SigT` | Generic | Signal type for state transitions |\n| `next()` | Method | Abstract transition function returning next state |\n| `signal` | Parameter | Optional external signal influencing transition |\n\n资料来源：[cyclic_agent/state.py:7-11]()\n\n### CyclicExecutor\n\nThe `CyclicExecutor` manages the runtime execution loop for state machines:\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| Method | Description |\n|--------|-------------|\n| `start(initial_state)` | Initiates the execution loop in a separate thread |\n| `pause()` | Halts execution without terminating |\n| `resume()` | Continues execution from paused state |\n| `kill()` | Stops the executor and joins the thread |\n\n资料来源：[cyclic_agent/executor.py:1-29]()\n\n## Execution Flow\n\n```mermaid\ngraph TD\n    A[Start: CyclicExecutor.start] --> B{self.running?}\n    B -->|Yes| C[state = state.next]\n    B -->|No| D[Wait]\n    C --> E[Sleep: default_time_interval]\n    E --> B\n    D --> B\n    F[Kill Signal] --> G[self.killed = True]\n    G --> B\n    B -->|self.killed| H[Exit Loop]\n```\n\nThe main loop continuously calls `state.next()` and sleeps for the configured interval. Thread safety is maintained through a lock that guards the `running` and `killed` flags. 资料来源：[cyclic_agent/executor.py:27-33]()\n\n## State Machine Structure\n\n### Typical State Implementation\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\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\nEach state class:\n1. Inherits from `State[SignalType]`\n2. Stores relevant data as Pydantic fields\n3. Implements `next()` returning the next state instance\n\n资料来源：[examples/hello_world/hello_world.py:13-26]()\n\n### State Transitions\n\n```mermaid\ngraph LR\n    A[AskQuestion] -->|next()| B[AnswerQuestion]\n    B -->|next()| A\n```\n\nThe cyclic nature allows indefinite chaining of states, enabling continuous autonomous operation. 资料来源：[README.md:27-42]()\n\n## Supporting Components\n\n### Memory Management (Fifo)\n\nThe `Fifo` class provides persistent memory for states:\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| Feature | Description |\n|---------|-------------|\n| `capacity` | Maximum stored items (default: 100) |\n| `add(item)` | Adds item with timestamp, auto-evicts oldest |\n| `prompt()` | Returns formatted history string |\n| Logging | All additions logged to file with timestamps |\n\n资料来源：[examples/bilibili_surfer/fifo.py:1-27]()\n\n### Base State Pattern\n\nComplex states inherit from a base class providing common functionality:\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        # LLM-based state inference logic\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:25-44]()\n\n## Advanced State Patterns\n\n### Chain of Thought (CoT)\n\nThe framework includes a `CoT` state for step-by-step reasoning:\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### Search State\n\nThe `Search` state provides a template for search operations:\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-16]()\n\n## Complex State Machine Example\n\nThe Bilibili Surfer example demonstrates a multi-state architecture:\n\n```mermaid\ngraph TD\n    A[BrowsingVideo] -->|next| B[ReadingComments]\n    A -->|next| A\n    B -->|next| C[PostComment]\n    B -->|next| A\n    C -->|next| A\n```\n\n| State | Purpose | Reachable States |\n|-------|---------|------------------|\n| `BrowsingVideo` | Search and select videos | `BrowsingVideo`, `ReadingComments` |\n| `ReadingComments` | View and select comments | `BrowsingVideo`, `ReadingComments`, `PostComment` |\n| `PostComment` | Reply to selected comment | `BrowsingVideo` |\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:60-130]()\n\n## Configuration and Threading\n\n### Executor Threading Model\n\n```mermaid\ngraph TD\n    subgraph MainThread\n        A[CyclicExecutor.start]\n    end\n    subgraph WorkerThread\n        B[_main_loop]\n        C[state.next]\n        D[time.sleep]\n    end\n    A -->|spawns| B\n    B --> C\n    C --> D\n    D --> B\n```\n\nThe executor spawns a dedicated thread for the main loop, ensuring non-blocking operation. The lock ensures safe modification of `running` and `killed` flags from external threads. 资料来源：[cyclic_agent/executor.py:16-18]()\n\n### Time Interval Configuration\n\n```python\nexecutor = CyclicExecutor(5)  # 5-second interval between state transitions\nexecutor.start(initial_state)\ntime.sleep(20)  # Main thread sleeps while executor runs\n```\n\nThe `default_time_interval` parameter controls the delay between state transitions, allowing rate limiting and API compliance. 资料来源：[examples/hello_world/hello_world.py:28-32]()\n\n## Summary\n\nThe CyclicAgent architecture provides:\n\n1. **State Pattern Foundation** - Generic, type-safe state classes with Pydantic\n2. **Cyclic Execution** - Infinite state transitions enabling autonomous agents\n3. **Thread-Safe Execution** - Lock-protected executor with pause/resume/kill controls\n4. **Memory Persistence** - FIFO-based history with file logging\n5. **Extensibility** - Abstract base classes for custom state implementations\n\nThe framework's simplicity—combining a base `State` class with an `Executor`—enables complex autonomous behaviors through composition of simple state transitions.\n\n---\n\n<a id='page-6'></a>\n\n## Creating Custom States\n\n### 相关页面\n\n相关主题：[State Base Class](#page-3), [Hello World Example](#page-8), [Bilibili Surfer Example](#page-9)\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- [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/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# Creating Custom States\n\n## Overview\n\nIn CyclicAgent, **states** are the fundamental building blocks of autonomous agents. Each state represents a distinct behavior or step in an agent's workflow, and states transition to one another through a well-defined interface. This design pattern enables the creation of complex, cyclic agent behaviors where execution can loop indefinitely through different states.\n\nThe framework abstracts an agent as a **finite state machine (FSM)** using the state design pattern. Each state implements a `next()` method that returns another state, creating an infinite transition chain that makes the agent \"cyclic.\" 资料来源：[README.md:12-14]()\n\n## Architecture\n\n### State Pattern Design\n\nThe `State` class serves as the abstract base for all agent states. It leverages Python's generic type system to provide type safety for signals passed between states.\n\n```mermaid\ngraph TD\n    A[State SigT] -->|extends| B[AskQuestion]\n    A -->|extends| C[AnswerQuestion]\n    A -->|extends| D[CustomState]\n    B -->|next() returns| C\n    C -->|next() returns| B\n    D -->|next() returns| E[NextState]\n```\n\n### Key Components\n\n| Component | File | Purpose |\n|-----------|------|---------|\n| `State[SigT]` | `cyclic_agent/state.py` | Abstract base class for all states |\n| `CyclicExecutor` | `cyclic_agent/executor.py` | Executes the state machine loop |\n| `CyclicExecutor.start()` | `cyclic_agent/executor.py` | Initiates the state machine |\n\n## Creating Basic States\n\n### Step 1: Define Your State Class\n\nExtend the `State` class and implement the `next()` method:\n\n```python\nfrom __future__ import annotations\nfrom cyclic_agent import State, CyclicExecutor\n\nclass MyState(State[None]):\n    def next(self, signal: None = None) -> AnotherState:\n        # Perform state actions\n        return AnotherState()\n```\n\n### Step 2: Implement State Logic\n\nThe `next()` method should contain the logic for the current state and return the next state to transition to:\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资料来源：[examples/hello_world/hello_world.py:14-18]()\n\n### Step 3: Create the State Transition Pair\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资料来源：[examples/hello_world/hello_world.py:21-26]()\n\n### Step 4: Execute the State Machine\n\n```python\nif __name__ == \"__main__\":\n    initial_state = AskQuestion()\n    executor = CyclicExecutor(5)  # 5-second interval between transitions\n    executor.start(initial_state)\n```\n\n资料来源：[examples/hello_world/hello_world.py:29-33]()\n\n## State API Reference\n\n### State Class\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:1-9]()\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `signal` | `SigT \\| None` | Optional signal passed to the state for external input |\n| **Returns** | `State[SigT]` | The next state in the transition chain |\n\n### State Data Model\n\nStates inherit from Pydantic's `BaseModel`, providing automatic validation and serialization:\n\n```python\nclass AnswerQuestion(State[None]):\n    question: str  # State-specific attribute\n```\n\n资料来源：[examples/hello_world/hello_world.py:20-21]()\n\n## CyclicExecutor\n\n### Execution Model\n\nThe `CyclicExecutor` runs the state machine in a background thread, transitioning between states at configurable intervals.\n\n```mermaid\ngraph TD\n    A[Start] --> B{self.running?}\n    B -->|Yes| C[state = state.next()]\n    B -->|No| D[Wait...]\n    C --> E[Sleep interval]\n    E --> B\n    D --> B\n    F[Kill] --> G[Exit loop]\n```\n\n### CyclicExecutor API\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:6-12]()\n\n| Method | Description |\n|--------|-------------|\n| `start(initial_state)` | Start execution with an initial state |\n| `pause()` | Pause the state machine |\n| `resume()` | Resume from pause |\n| `kill()` | Stop execution completely |\n\n### Thread Safety\n\nThe executor uses a threading lock to ensure thread-safe state transitions:\n\n```python\ndef pause(self):\n    with self.lock:\n        self.running = False\n```\n\n资料来源：[cyclic_agent/executor.py:27-29]()\n\n## Advanced State Patterns\n\n### States with Memory\n\nComplex agents often need to remember past actions. States can include memory components:\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:16-22]()\n\n### FIFO Memory Implementation\n\n```python\nclass Fifo:\n    def __init__(self):\n        self.capacity = 100\n        self.queue = []\n\n    def add(self, item):\n        if len(self.queue) >= self.capacity:\n            self.queue.pop(0)\n        self.queue.append(item)\n\n    def prompt(self):\n        return \"\\n\".join([f\"{time} - {text}\" for text, time in reversed(self.queue)])\n```\n\n资料来源：[examples/bilibili_surfer/fifo.py:1-19]()\n\n### State-Independent Transitions\n\nStates can transition to different next states based on internal logic using pattern matching:\n\n```python\nmatch 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:58-63]()\n\n### State Inference Helper\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        \"\"\"\n    )\n    text = self.co.chat(temperature=1, message=prompt).text\n    return text\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:25-36]()\n\n## Type Aliases for State Transitions\n\nCyclicAgent uses Python type aliases to define valid state transitions, enabling static type checking:\n\n```python\ntype BrowsingVideoReachable = Union[BrowsingVideo, ReadingComments]\ntype ReadingCommentsReachable = Union[BrowsingVideo, ReadingComments, PostComment]\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:13-14]()\n\n## Complete Example: Two-State Loop\n\n```python\nfrom __future__ import annotations\nimport os\nimport time\nimport cohere\nfrom dotenv import load_dotenv\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资料来源：[examples/hello_world/hello_world.py:1-33]()\n\n## Best Practices\n\n### Forward References\n\nAlways use `from __future__ import annotations` for forward references in type hints:\n\n```python\nfrom __future__ import annotations\n```\n\n### State Immutability\n\nReturn new state instances rather than modifying existing ones to ensure thread safety:\n\n```python\ndef next(self, signal: None = None) -> AskQuestion:\n    return AskQuestion()  # Return new instance\n```\n\n### Signal Usage\n\nLeverage the signal parameter for external state control:\n\n```python\nclass ControlledState(State[str]):\n    def next(self, signal: str | None = None) -> State:\n        if signal == \"exit\":\n            return ExitState()\n        return AnotherState()\n```\n\n### Pydantic Configuration\n\nUse `ConfigDict(arbitrary_types_allowed=True)` when states contain non-Pydantic types like external clients or credentials:\n\n```python\nmodel_config = ConfigDict(arbitrary_types_allowed=True)\n```\n\n## Execution Flow\n\n```mermaid\nsequenceDiagram\n    participant User\n    participant Executor\n    participant State1\n    participant State2\n    \n    User->>Executor: start(AskQuestion)\n    Executor->>State1: next()\n    State1-->>Executor: AnswerQuestion\n    Executor->>State2: next()\n    State2-->>Executor: AskQuestion\n    Executor->>State1: next()\n    Note over Executor: Loop continues...\n```\n\n## Summary\n\nCreating custom states in CyclicAgent involves:\n\n1. **Extending** `State[SigT]` with your state class\n2. **Implementing** the `next()` method with state logic and transitions\n3. **Using** Pydantic for data model attributes\n4. **Executing** through `CyclicExecutor` with configurable intervals\n5. **Leveraging** memory and state inference for complex behaviors\n\nThe state pattern enables modular, maintainable agent design where each state is independent and transitions are explicit, making the agent behavior predictable and debuggable.\n\n---\n\n<a id='page-7'></a>\n\n## Memory Management with Fifo\n\n### 相关页面\n\n相关主题：[System Architecture](#page-5), [Bilibili Surfer Example](#page-9)\n\n<details>\n<summary>Related Source Files</summary>\n\n以下源码文件用于生成本页说明：\n\n- [examples/bilibili_surfer/fifo.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.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# Memory Management with Fifo\n\n## Overview\n\nThe `Fifo` class implements a First-In-First-Out (FIFO) memory buffer for the CyclicAgent framework. It serves as a persistent memory mechanism that tracks agent actions over time, enabling stateful behavior across multiple execution cycles. The memory stores action records with timestamps and provides a formatted prompt interface for LLM consumption.\n\n**Purpose and Scope:**\n- Maintains a rolling history of agent actions with temporal ordering\n- Persists memory entries to a log file for debugging and auditability\n- Provides context to language models about past agent behavior\n- Enforces a configurable capacity limit to prevent unbounded memory growth\n\n资料来源：[examples/bilibili_surfer/fifo.py:1-35](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n\n## Architecture\n\nThe `Fifo` class is a simple yet effective memory component that integrates with the broader `BilibiliStateBase` abstraction. It operates as a bounded queue with automatic eviction of oldest entries.\n\n```mermaid\ngraph TD\n    A[Agent Action] -->|add| B[Fifo Memory]\n    B --> C{Capacity Check}\n    C -->|queue full| D[Evict Oldest Entry]\n    C -->|space available| E[Append to Queue]\n    D --> E\n    E --> F[Log to fifo_log.txt]\n    F --> G[Timestamp Added]\n    G --> H[Memory Buffer]\n    H --> I[LLM Context via prompt]\n    \n    style A fill:#e1f5fe\n    style I fill:#fff3e0\n```\n\nThe memory flows into agent decision-making through the `_infer_state_helper` method, which includes past actions in LLM prompts.\n\n资料来源：[examples/bilibili_surfer/fifo.py:1-35](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:38-52](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n\n## Class Reference\n\n### Fifo\n\nThe core memory management class.\n\n| Attribute | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `capacity` | `int` | `100` | Maximum number of entries before oldest eviction |\n| `queue` | `list` | `[]` | Internal storage for memory entries |\n| `log_file` | `str` | `\"fifo_log.txt\"` | Path to persistent log file |\n\n#### Methods\n\n##### `__init__()`\n\nInitializes the Fifo instance and ensures the log file exists.\n\n```python\ndef __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资料来源：[examples/bilibili_surfer/fifo.py:6-14](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n\n##### `add(item: str) -> None`\n\nAdds a string item to the memory buffer.\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `item` | `str` | The action/event string to record |\n\n**Behavior:**\n1. Validates that `item` is a string (raises `ValueError` otherwise)\n2. If capacity is reached, removes the oldest entry from index 0\n3. Attaches a timestamp in `YYYY-MM-DD HH:MM:SS` format\n4. Appends the tuple `(item, timestamp)` to the queue\n5. Logs the entry to the file system\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)  # Remove the oldest item to maintain capacity\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\n资料来源：[examples/bilibili_surfer/fifo.py:16-23](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n\n##### `prompt() -> str`\n\nGenerates a formatted string of all memory entries for LLM consumption.\n\n**Returns:** A newline-separated string with entries in reverse chronological order (most recent first), formatted as `{time} - {text}`.\n\n```python\ndef prompt(self):\n    return \"\\n\".join([f\"{time} - {text}\" for text, time in reversed(self.queue)])\n```\n\n资料来源：[examples/bilibili_surfer/fifo.py:30-31](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n\n##### `log_to_file(item: str, timestamp: str) -> None`\n\nAppends a timestamped entry to the persistent log file.\n\n```python\ndef log_to_file(self, item, timestamp):\n    with open(self.log_file, 'a') as file:\n        file.write(f\"{timestamp} - {item}\\n\")\n```\n\n资料来源：[examples/bilibili_surfer/fifo.py:25-28](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n\n## Integration with State Machine\n\nThe `Fifo` memory is integrated into the agent architecture through the `BilibiliStateBase` abstract base class, which composes the memory buffer with other required components.\n\n```mermaid\ngraph LR\n    A[BilibiliStateBase] --> B[Fifo Memory]\n    A --> C[Cohere Client]\n    A --> D[Bilibili Credential]\n    A --> E[Initial Prompt]\n    \n    F[_infer_state_helper] --> B\n    G[BrowsingVideo] --> A\n    H[ReadingComments] --> A\n    I[PostComment] --> A\n```\n\n**Base Class Composition:**\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:29-35](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n\n## Usage Patterns\n\n### Adding Memory Entries\n\nAgents record actions by calling `memory.add()` with descriptive strings:\n\n```python\n# Track search operations\nself.memory.add(f\"searched for {response} while browsing video\")\n\n# Record comment discovery\nself.memory.add(f\"finds comment: {cmt['content']['message']} while browsing {self.video_title}\")\n\n# Log posting activity\nself.memory.add(f\"commented {response} to {self.video_title}\")\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:88](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:108](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n\n### Including Memory in LLM Prompts\n\nThe `_infer_state_helper` method constructs prompts that include memory context:\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```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:38-49](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n\n### Initialization\n\nFifo is instantiated empty and passed to the initial state:\n\n```python\ninitial_state = BrowsingVideo(memory=Fifo(),\n                              initial_prompt=initial_prompt,\n                              co=Client(os.environ.get(\"COHERE_API_KEY\")),\n                              credential=Credential(...))\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:135-142](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n\n## Behavior Specifications\n\n| Aspect | Specification |\n|--------|---------------|\n| **Eviction Policy** | Oldest entry removed when capacity (100) is exceeded |\n| **Ordering** | Queue maintains insertion order; prompt reverses for recency-first display |\n| **Persistence** | All additions logged to `fifo_log.txt` in append mode |\n| **Type Constraint** | Only string values accepted; raises `ValueError` for non-strings |\n| **Timestamp Format** | ISO-style: `YYYY-MM-DD HH:MM:SS` |\n\n## Limitations and Considerations\n\n1. **Fixed Capacity**: The 100-item limit is hardcoded and cannot be configured per-instance without modifying source code.\n2. **File I/O on Every Add**: Each memory addition triggers a synchronous file write, which may impact performance in high-frequency scenarios.\n3. **No Query Filtering**: The `prompt()` method returns all entries; there is no mechanism to retrieve a subset by time range or pattern.\n4. **Shared Log File**: All instances write to `fifo_log.txt` by default; concurrent access from multiple processes may cause race conditions.\n\n---\n\n<a id='page-8'></a>\n\n## Hello World Example\n\n### 相关页面\n\n相关主题：[Installation and Setup](#page-1), [Creating Custom States](#page-6), [Bilibili Surfer Example](#page-9)\n\n<details>\n<summary>Relevant Source Files</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</details>\n\n# Hello World Example\n\n## Overview\n\nThe Hello World Example (`examples/hello_world/hello_world.py`) is the simplest demonstration of the CyclicAgent framework. It showcases the core state machine pattern by creating two mutually transitioning states that simulate a continuous question-answer loop using a Cohere LLM. 资料来源：[examples/hello_world/hello_world.py:1-31]()\n\n## Architecture\n\nCyclicAgent abstracts an agent as a **Finite State Machine (FSM)** using the State design pattern. Each state implements a `next()` method that returns another state, enabling indefinite chaining of transitions. 资料来源：[README.md](https://github.com/xingjianll/cyclic-agent#how-does-cyclicagent-work)\n\n### State Machine Diagram\n\n```mermaid\ngraph TD\n    A((Start)) --> B[AskQuestion State]\n    B -->|next()| C[AnswerQuestion State]\n    C -->|next()| B\n    B -->|5 iterations| D((End))\n    C -->|5 iterations| D\n```\n\n## Core Components\n\n### State Base Class\n\nThe `State` class is the foundation of the framework, defined as a generic Pydantic model:\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:5-9]()\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `SigT` | Generic TypeVar | Signal type for state communication |\n| `next()` | Abstract Method | Returns the next state in the FSM |\n\n### CyclicExecutor\n\nThe executor manages the state machine lifecycle:\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-8]()\n\n| Method | Description |\n|--------|-------------|\n| `start(initial_state)` | Begins executing the FSM in a separate thread |\n| `pause()` | Pauses execution (thread-safe) |\n| `resume()` | Resumes execution (thread-safe) |\n| `kill()` | Stops execution and joins the thread |\n\n## Example Implementation\n\n### AskQuestion State\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资料来源：[examples/hello_world/hello_world.py:13-18]()\n\n| Field | Type | Description |\n|-------|------|-------------|\n| Signal Type | `None` | This state does not accept external signals |\n| Return Type | `AnswerQuestion` | Transitions to the answer state with the question |\n\n### AnswerQuestion State\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资料来源：[examples/hello_world/hello_world.py:20-25]()\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `question` | `str` | Stored question from previous state |\n| Signal Type | `None` | Does not accept external signals |\n| Return Type | `AskQuestion` | Transitions back to ask a new question |\n\n## Execution Flow\n\n```mermaid\nsequenceDiagram\n    participant Main\n    participant Executor\n    participant AskQuestion\n    participant AnswerQuestion\n    participant CohereAPI\n\n    Main->>Executor: start(AskQuestion())\n    Executor->>AskQuestion: next()\n    AskQuestion->>CohereAPI: chat(\"Ask a question\")\n    CohereAPI-->>AskQuestion: question_text\n    AskQuestion->>AnswerQuestion: next(question=...)\n    \n    loop 5 times\n        Executor->>AnswerQuestion: next()\n        AnswerQuestion->>CohereAPI: chat(question)\n        CohereAPI-->>AnswerQuestion: answer\n        AnswerQuestion->>AskQuestion: next()\n        Executor->>AskQuestion: next()\n        AskQuestion->>CohereAPI: chat(\"Ask a question\")\n        CohereAPI-->>AskQuestion: new_question\n        AskQuestion->>AnswerQuestion: next(question=...)\n    end\n```\n\n## Configuration\n\n### Environment Setup\n\nThe example requires a `.env` file with the Cohere API key:\n\n```bash\nCOHERE_API_KEY=your_api_key_here\n```\n\n### Executor Configuration\n\n```python\nexecutor = CyclicExecutor(5)  # 5-second interval between state transitions\n```\n\n资料来源：[examples/hello_world/hello_world.py:28-29]()\n\n| Parameter | Value | Description |\n|-----------|-------|-------------|\n| `default_time_interval` | `5` (seconds) | Pause between each `next()` call |\n| `time.sleep(20)` | `20` (seconds) | Total runtime before natural exit |\n\n## Key Takeaways\n\n1. **State Pattern**: Each state is a Pydantic model that implements `next()`, returning the subsequent state 资料来源：[cyclic_agent/state.py:5-9]()\n\n2. **Thread Safety**: The executor uses `threading.Lock` for safe pause/resume/kill operations 资料来源：[cyclic_agent/executor.py:4]()\n\n3. **Type Safety**: Generic type parameters (`State[SigT]`) ensure compile-time safety for signal types 资料来源：[cyclic_agent/state.py:5]()\n\n4. **Extensibility**: New states can be added by inheriting from `State` and implementing the `next()` method\n\n## Running the Example\n\n```bash\n# Install dependencies\npip install cyclic-agent cohere python-dotenv\n\n# Set up environment\nexport COHERE_API_KEY=your_key\n\n# Run\npython examples/hello_world/hello_world.py\n```\n\nThe example will print alternating questions and answers for approximately 20 seconds before exiting.\n\n---\n\n<a id='page-9'></a>\n\n## Bilibili Surfer Example\n\n### 相关页面\n\n相关主题：[Creating Custom States](#page-6), [Memory Management with Fifo](#page-7), [Hello World Example](#page-8)\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 Example\n\nThe Bilibili Surfer is a demonstration application built on the CyclicAgent framework that creates an autonomous AI agent capable of browsing Bilibili, a Chinese video-sharing platform. The agent autonomously searches for videos, reads comments, and interacts by posting replies, simulating a realistic user experience with automatic disclosure as a bot.\n\n## Architecture Overview\n\nThe Bilibili Surfer exemplifies the CyclicAgent's finite state machine (FSM) design pattern. The agent operates as a cyclical state machine where each state implements a `next()` method that returns the subsequent state, enabling indefinite chaining of state transitions.\n\n```mermaid\ngraph TD\n    A([BrowsingVideo]) -->|select video| B([ReadingComments])\n    A -->|search again| A\n    B -->|select comment| C([PostComment])\n    B -->|back to browse| A\n    C -->|complete| A\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:1-150]()\n\n## State Components\n\n### BilibiliStateBase (Abstract Base)\n\nAll Bilibili states inherit from `BilibiliStateBase`, which combines the `State` abstract class with common attributes required across all states.\n\n| Attribute | Type | Description |\n|-----------|------|-------------|\n| `memory` | `Fifo` | Queue storing past agent actions with timestamps |\n| `co` | `Client` | Cohere API client for LLM interactions |\n| `credential` | `Credential` | Bilibili API authentication credentials |\n| `initial_prompt` | `str` | System prompt defining agent persona |\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:35-43]()\n\nThe base class provides the `_infer_state_helper()` method that constructs prompts for LLM-based state inference:\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```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:45-58]()\n\n### BrowsingVideo State\n\nThe entry point state where the agent searches for and selects videos to watch.\n\n**Type Definition:**\n```python\ntype BrowsingVideoReachable = Union[BrowsingVideo, ReadingComments]\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:61-62]()\n\n**Workflow:**\n\n1. Generate a search keyword phrase via LLM (max 3 Chinese words)\n2. Execute Bilibili video search ordered by fan count\n3. Present top 10 results to LLM for selection\n4. Log selection to memory\n5. Transition to `ReadingComments` or remain in `BrowsingVideo`\n\n```python\ndef next(self, signal: None = None) -> BrowsingVideoReachable:\n    print('BrowsingVideo')\n    prompt = I(\n        f\"\"\"\n        {self.initial_prompt}\n        Here are your past actions {self.memory.prompt()} Generate a keyword phrase for videos you want to watch.\n        Be creative and avoid repeating. Respond with a maximum of three words in Chinese.\n        \"\"\"\n    )\n    response = self.co.chat(temperature=1, message=prompt).text\n    res = asyncio.run(search.search_by_type(response,\n                                            search_type=search.SearchObjectType.VIDEO,\n                                            order_type=search.OrderUser.FANS,\n                                            order_sort=0\n                                            )\n                      )\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:64-79]()\n\n### ReadingComments State\n\nEnables the agent to examine and select comments from a specific video for potential interaction.\n\n**Type Definition:**\n```python\ntype ReadingCommentsReachable = Union[BrowsingVideo, ReadingComments, PostComment]\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:118-119]()\n\n**Required Attributes:**\n\n| Attribute | Type | Description |\n|-----------|------|-------------|\n| `video_bvid` | `str` | Bilibili video BV identifier |\n| `video_title` | `str` | Video title for context |\n| `video_description` | `str` | Video description for context |\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:121-126]()\n\n**Workflow:**\n\n1. Fetch top comments ordered by likes via Bilibili API\n2. Present comments to LLM for selection\n3. Based on LLM decision, either:\n   - Return to `BrowsingVideo`\n   - Stay in `ReadingComments`\n   - Transition to `PostComment` with reply context\n\n```python\nmatch self._infer_state_helper('BrowsingVideo', 'ReadingComments', 'PostComment'):\n    case 'BrowsingVideo':\n        return BrowsingVideo(**self.model_dump(exclude={'video_bvid', 'video_title', 'video_description'}))\n    case 'ReadingComments':\n        return self\n    case 'PostComment':\n        return PostComment(**self.model_dump(), reply_to=cmt['content']['message'], reply_to_oid=cmt['oid'])\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:141-148]()\n\n### PostComment State\n\nHandles automatic reply generation and posting to Bilibili.\n\n**Type Definition:**\n```python\ntype PostCommentReachable = Union[BrowsingVideo]\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:93-94]()\n\n**Attributes:**\n\n| Attribute | Type | Description |\n|-----------|------|-------------|\n| `reply_to` | `str \\| None` | Original comment content being replied to |\n| `reply_to_oid` | `int \\| None` | Original comment OID for threading |\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:96-99]()\n\n**Workflow:**\n\n1. Generate reply content via LLM based on:\n   - Original comment being replied to\n   - Video context (title, description)\n2. Append automatic disclosure footnote\n3. Post comment to video via Bilibili API\n4. Create and publish a Bilibili \"Dynamic\" (post) with:\n   - Video link\n   - Reply content\n   - Disclosure notice\n5. Return to `BrowsingVideo` state\n\n```python\nresponse = self.co.chat(temperature=1, message=prompt).text\nfootnote = (\n    f\"\\n I am a bot, and this action was performed automatically. Please contact {os.getenv('name')}\"\n    f\" if you have any questions or concerns.\"\n)\nasyncio.run(comment.send_comment(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资料来源：[examples/bilibili_surfer/bilibili_surfer.py:106-117]()\n\n## Memory System: Fifo\n\nThe `Fifo` class implements a bounded queue for storing agent action history, providing the agent with contextual awareness of past behaviors.\n\n资料来源：[examples/bilibili_surfer/fifo.py:1-25]()\n\n### Configuration\n\n| Parameter | Default | Description |\n|-----------|---------|-------------|\n| `capacity` | 100 | Maximum stored actions before oldest are evicted |\n| `log_file` | `\"fifo_log.txt\"` | Persistent log file for action history |\n\n### Core Methods\n\n| Method | Description |\n|--------|-------------|\n| `add(item: str)` | Appends action with timestamp, evicts oldest if at capacity |\n| `prompt()` | Returns formatted history string (newest first) |\n\n```python\ndef prompt(self):\n    return \"\\n\".join([f\"{time} - {text}\" for text, time in reversed(self.queue)])\n```\n\n资料来源：[examples/bilibili_surfer/fifo.py:24-25]()\n\n## Execution Model\n\nThe `CyclicExecutor` manages the state machine lifecycle in a dedicated thread.\n\n资料来源：[cyclic_agent/executor.py:1-47]()\n\n### Executor Configuration\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `default_time_interval` | `float` | Seconds between state transitions |\n| `running` | `bool` | Execution status flag |\n| `killed` | `bool` | Permanent stop signal |\n\n### Control Methods\n\n| Method | Description |\n|--------|-------------|\n| `start(initial_state)` | Launch executor thread with initial state |\n| `pause()` | Suspend state transitions |\n| `resume()` | Continue suspended execution |\n| `kill()` | Stop execution and join thread |\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:36-44]()\n\n## Data Flow Diagram\n\n```mermaid\nsequenceDiagram\n    participant User\n    participant Executor\n    participant LLM as Cohere LLM\n    participant Bilibili as Bilibili API\n    participant Memory as Fifo Memory\n\n    Executor->>BrowsingVideo: start(initial_state)\n    BrowsingVideo->>LLM: Generate search query\n    BrowsingVideo->>Bilibili: search.search_by_type()\n    Bilibili-->>BrowsingVideo: Top 10 videos\n    BrowsingVideo->>Memory: add(finds {title})\n    BrowsingVideo->>ReadingComments: next()\n\n    ReadingComments->>Bilibili: comment.get_comments()\n    Bilibili-->>ReadingComments: Top 5 comments\n    ReadingComments->>Memory: add(find comment)\n    ReadingComments->>PostComment: next(reply_to)\n\n    PostComment->>LLM: Generate reply\n    PostComment->>Memory: add(commented)\n    PostComment->>Bilibili: comment.send_comment()\n    PostComment->>Bilibili: dynamic.send_dynamic()\n    PostComment->>BrowsingVideo: next()\n```\n\n## Setup and Usage\n\n### Prerequisites\n\nRequired environment variables:\n\n| Variable | Description |\n|----------|-------------|\n| `COHERE_API_KEY` | Cohere API key for LLM access |\n| `SESSDATA` | Bilibili session data cookie |\n| `BILI_JCT` | Bilibili CSRF token |\n| `BUVID3` | Bilibili user identifier cookie |\n| `name` | Contact name for bot disclosure |\n\n### Running the Example\n\n```python\nif __name__ == \"__main__\":\n    initial_prompt = \"You are a dude browsing Bilibili, A Chinese video sharing platform.\"\n\n    initial_state = BrowsingVideo(memory=Fifo(),\n                                  initial_prompt=initial_prompt,\n                                  co=Client(os.environ.get(\"COHERE_API_KEY\")),\n                                  credential=Credential(sessdata=SESSDATA,\n                                                        bili_jct=BILI_JCT,\n                                                        buvid3=BUVID3\n                                                        )\n                                  )\n    executor = CyclicExecutor(5)  # 5-second intervals\n    executor.start(initial_state)\n    time.sleep(1000)  # Run for ~16 minutes\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:163-180]()\n\n## State Transition Matrix\n\n| Current State | Action | Next State |\n|---------------|--------|------------|\n| `BrowsingVideo` | Select video | `ReadingComments` |\n| `BrowsingVideo` | Search again | `BrowsingVideo` |\n| `ReadingComments` | Choose comment | `PostComment` |\n| `ReadingComments` | Browse more | `BrowsingVideo` |\n| `ReadingComments` | Stay | `ReadingComments` |\n| `PostComment` | Complete | `BrowsingVideo` |\n\n## Integration with Core Framework\n\nThe Bilibili Surfer demonstrates CyclicAgent's extensibility:\n\n1. **State Pattern**: Each state extends `State[None]`, implementing the `next()` abstract method\n   - 资料来源：[cyclic_agent/state.py:1-15]()\n\n2. **Type Annotations**: Python 3.12+ type unions define reachable states for type safety\n   - 资料来源：[cyclic_agent/__init__.py:1-6]()\n\n3. **Pydantic Models**: States use `BaseModel` for automatic serialization and validation\n   - 资料来源：[cyclic_agent/state.py:5]()\n\n4. **Dependency Injection**: States receive dependencies via constructor, enabling testability\n\n---\n\n<a id='page-10'></a>\n\n## Helper States\n\n### 相关页面\n\n相关主题：[State Base Class](#page-3), [Creating Custom States](#page-6)\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/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/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# Helper States\n\n## Overview\n\nHelper States are reusable, composable state components in CyclicAgent that encapsulate common patterns for LLM-powered agent workflows. They serve as building blocks that developers can extend, combine, or integrate into custom state machines to accelerate agent development.\n\nUnlike application-specific states (e.g., `AskQuestion` or `BrowsingVideo`), helper states focus on generic operational patterns such as search, chain-of-thought reasoning, and callback-driven transitions. They follow the same finite state machine (FSM) architecture as all states in CyclicAgent, ensuring seamless integration with the `CyclicExecutor`.\n\n资料来源：[cyclic_agent/__init__.py:1-6]()\n\n## Architecture\n\nHelper states inherit from the base `State` class and implement the `next()` method to define transitions. They typically leverage callbacks for flexible exit behavior, allowing parent states to control the flow after the helper completes its operation.\n\n```mermaid\ngraph TD\n    A[Parent State] -->|creates| B[Helper State]\n    B -->|executes operation| C[Result/Action]\n    C -->|callback| D[Exit Callback]\n    D -->|returns| A[Parent State or Next State]\n```\n\n### Base State Contract\n\nAll states, including helpers, must implement:\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-9]()\n\n## Chain of Thought (CoT) Helper\n\n### Purpose\n\nThe `CoT` class provides a reusable wrapper for chain-of-thought reasoning patterns. It automatically appends \"Let's think step by step.\" to prompts, enabling step-by-step reasoning in LLM responses.\n\n资料来源：[cyclic_agent/cot.py:1-5]()\n\n### Class Definition\n\n```python\nclass CoT(State[None]):\n    exit_: Callable[[str], State]\n    llm: State\n    prompt: str\n```\n\n### Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `exit_` | `Callable[[str], State]` | Callback invoked with the LLM's response; returns the next state |\n| `llm` | `State` | The LLM state used to generate responses |\n| `prompt` | `str` | The base prompt to which chain-of-thought suffix is added |\n\n### Implementation\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\n资料来源：[cyclic_agent/cot.py:7-14]()\n\n### Usage Pattern\n\nThe `CoT` helper demonstrates a callback-driven transition pattern where:\n\n1. The helper augments the prompt with reasoning instructions\n2. The LLM processes the enhanced prompt\n3. The result is passed to the exit callback\n4. Control returns to the calling state or transitions to a new state\n\n```mermaid\nsequenceDiagram\n    participant P as Parent State\n    participant C as CoT Helper\n    participant L as LLM State\n    participant E as Exit Callback\n    \n    P->>C: Creates CoT with prompt, llm, exit_\n    C->>C: Appends \"Let's think step by step.\"\n    C->>L: Calls llm with enhanced prompt\n    L-->>C: Returns reasoning answer\n    C->>E: Invokes callback with answer\n    E-->>P: Returns next State\n```\n\n## Search Helper\n\n### Purpose\n\nThe `Search` class provides a generic search operation pattern. It accepts a query, executes a search (to be implemented by subclass), and passes results to an exit callback for further processing.\n\n资料来源：[cyclic_agent/search.py:1-5]()\n\n### Class Definition\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### Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `query` | `str` | The search query string |\n| `exit_` | `Callable[[list[str]], State]` | Callback receiving search results; returns the next state |\n\n### Key Design Patterns\n\n1. **Abstract Search Method**: The `search()` method raises `NotImplementedError`, requiring subclasses to provide concrete implementations.\n2. **Typed Callback**: The exit callback uses `Annotated` to document that it receives search results as a list of strings.\n3. **Separation of Concerns**: Search logic is decoupled from state transition logic.\n\n资料来源：[cyclic_agent/search.py:6-12]()\n\n### Subclass Implementation Example\n\n```python\nclass VideoSearch(Search):\n    def search(self, query: str) -> str:\n        # Concrete implementation\n        results = video_api.search(query)\n        return formatted_results\n```\n\n## Callback-Driven Transition Pattern\n\nBoth helper states employ a consistent callback pattern for state transitions:\n\n```mermaid\ngraph LR\n    A[Helper State] --> B{Operation Complete}\n    B --> C[Exit Callback]\n    C --> D[Next State]\n    D --> E[CyclicExecutor]\n    E --> A\n```\n\n### Benefits\n\n| Benefit | Description |\n|---------|-------------|\n| **Decoupling** | Helper states don't need to know about subsequent states |\n| **Composability** | Same helper can be reused with different callbacks |\n| **Flexibility** | Callbacks can implement complex routing logic |\n| **Testability** | Callbacks can be easily mocked for unit testing |\n\n## Integration with CyclicExecutor\n\nHelper states integrate seamlessly with the executor:\n\n```python\nclass CyclicExecutor:\n    def _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:26-32]()\n\nThe executor continuously calls `next()` on any state, including helpers. Each helper's `next()` either:\n- Returns another state (transition)\n- Returns the same state (loop continuation)\n\n## Creating Custom Helper States\n\n### Template\n\n```python\nfrom cyclic_agent import State\n\nclass MyHelper(State[None]):\n    data: str\n    exit_: Callable[[ResultType], State]\n\n    def next(self, signal: None = None) -> State:\n        # Perform helper operation\n        result = self.perform_operation()\n        # Delegate to callback for next state\n        return self.exit_(result)\n\n    def perform_operation(self) -> ResultType:\n        raise NotImplementedError\n```\n\n### Checklist\n\n- [ ] Inherit from `State[None]`\n- [ ] Define exit callback as `Callable` parameter\n- [ ] Implement `next()` method returning `State`\n- [ ] Call exit callback with operation result\n- [ ] Raise `NotImplementedError` for subclass-specific methods\n\n## Comparison: CoT vs Search Helpers\n\n| Aspect | CoT | Search |\n|--------|-----|--------|\n| **Primary Function** | Reasoning wrapper | Search operation |\n| **Exit Callback Parameter** | `Callable[[str], State]` | `Callable[[list[str]], State]` |\n| **Abstract Methods** | None | `search(query: str)` |\n| **Prompt Modification** | Appends reasoning suffix | None |\n| **Use Case** | Step-by-step reasoning | Information retrieval |\n\n## Export Configuration\n\nHelper states are available via the cyclic_agent package:\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\n\n__all__ = [\"State\", \"CyclicExecutor\"]\n```\n\nDirect imports for specific helpers:\n\n```python\nfrom cyclic_agent.cot import CoT\nfrom cyclic_agent.search import Search\n```\n\n资料来源：[cyclic_agent/__init__.py:1-6]()\n\n## Best Practices\n\n1. **Use Helpers as Building Blocks**: Compose helpers within custom states rather than subclassing them.\n2. **Type Your Callbacks**: Always specify callback signatures for type safety.\n3. **Handle Edge Cases**: Implement error handling in `next()` for production use.\n4. **Document State Transitions**: Use type aliases (e.g., `ReachableStates`) to document possible transitions.\n5. **Maintain State Immutability**: Helper states should not mutate shared state; use callbacks for side effects.\n\n---\n\n---\n\n## Doramagic Pitfall Log\n\nProject: xingjianll/cyclic-agent\n\nSummary: Found 6 potential pitfall items; 0 are high/blocking. Highest priority: capability - 能力判断依赖假设.\n\n## 1. capability · 能力判断依赖假设\n\n- Severity: medium\n- Evidence strength: source_linked\n- Finding: README/documentation is current enough for a first validation pass.\n- User impact: 假设不成立时，用户拿不到承诺的能力。\n- Suggested check: 将假设转成下游验证清单。\n- Guardrail action: 假设必须转成验证项；没有验证结果前不能写成事实。\n- Evidence: capability.assumptions | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | README/documentation is current enough for a first validation pass.\n\n## 2. maintenance · 维护活跃度未知\n\n- Severity: medium\n- Evidence strength: source_linked\n- Finding: 未记录 last_activity_observed。\n- User impact: 新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。\n- Suggested check: 补 GitHub 最近 commit、release、issue/PR 响应信号。\n- Guardrail action: 维护活跃度未知时，推荐强度不能标为高信任。\n- Evidence: evidence.maintainer_signals | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | last_activity_observed missing\n\n## 3. security_permissions · 下游验证发现风险项\n\n- Severity: medium\n- Evidence strength: source_linked\n- Finding: no_demo\n- User impact: 下游已经要求复核，不能在页面中弱化。\n- Suggested check: 进入安全/权限治理复核队列。\n- Guardrail action: 下游风险存在时必须保持 review/recommendation 降级。\n- Evidence: downstream_validation.risk_items | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | no_demo; severity=medium\n\n## 4. security_permissions · 存在评分风险\n\n- Severity: medium\n- Evidence strength: source_linked\n- Finding: no_demo\n- User impact: 风险会影响是否适合普通用户安装。\n- Suggested check: 把风险写入边界卡，并确认是否需要人工复核。\n- Guardrail action: 评分风险必须进入边界卡，不能只作为内部分数。\n- Evidence: risks.scoring_risks | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | no_demo; severity=medium\n\n## 5. maintenance · issue/PR 响应质量未知\n\n- Severity: low\n- Evidence strength: source_linked\n- Finding: issue_or_pr_quality=unknown。\n- User impact: 用户无法判断遇到问题后是否有人维护。\n- Suggested check: 抽样最近 issue/PR，判断是否长期无人处理。\n- Guardrail action: issue/PR 响应未知时，必须提示维护风险。\n- Evidence: evidence.maintainer_signals | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | issue_or_pr_quality=unknown\n\n## 6. maintenance · 发布节奏不明确\n\n- Severity: low\n- Evidence strength: source_linked\n- Finding: release_recency=unknown。\n- User impact: 安装命令和文档可能落后于代码，用户踩坑概率升高。\n- Suggested check: 确认最近 release/tag 和 README 安装命令是否一致。\n- Guardrail action: 发布节奏未知或过期时，安装说明必须标注可能漂移。\n- Evidence: 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 output with a Doramagic pitfall appendix.",
      "title": "cyclic-agent 说明书",
      "toc": [
        "https://github.com/xingjianll/cyclic-agent 项目说明书",
        "目录",
        "Installation and Setup",
        "Overview",
        "Prerequisites",
        "Installation Methods",
        "Project Configuration",
        "LLM Configuration",
        "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\nThe following material strengthens the Repomix/AI Context Pack body. Human Manual is only a reading skeleton; pitfall logs become hard operating constraints for the host AI.\n\n## Human Manual Skeleton\n\nUsage rule: this is only a reading path and salience signal, not factual authority. Concrete facts must still come from repo evidence / Claim Graph.\n\nHard rules for the host AI:\n- Do not treat page titles, order, summaries, or importance as project facts.\n- When explaining the Human Manual skeleton, state that it is only a reading path / salience signal.\n- Capability, installation, compatibility, runtime status, and risk judgments must cite repo evidence, source paths, or Claim Graph.\n\n- **Installation and Setup**：importance `high`\n  - source_paths: pyproject.toml, README.md\n- **Project Overview**：importance `high`\n  - source_paths: README.md\n- **State Base Class**：importance `high`\n  - source_paths: cyclic_agent/state.py, cyclic_agent/__init__.py\n- **CyclicExecutor**：importance `high`\n  - source_paths: cyclic_agent/executor.py\n- **System Architecture**：importance `high`\n  - source_paths: cyclic_agent/executor.py, cyclic_agent/state.py, examples/bilibili_surfer/bilibili_surfer.py\n- **Creating Custom States**：importance `high`\n  - source_paths: cyclic_agent/state.py, examples/hello_world/hello_world.py\n- **Memory Management with Fifo**：importance `medium`\n  - source_paths: examples/bilibili_surfer/fifo.py, examples/bilibili_surfer/bilibili_surfer.py\n- **Hello World Example**：importance `high`\n  - source_paths: examples/hello_world/hello_world.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\nHard rules for the host AI:\n- Without repo_clone_verified=true, do not claim the source code has been read.\n- Without repo_inspection_verified=true, do not turn README/docs/package observations into facts.\n- Without quick_start_verified=true, do not claim the Quick Start has been successfully run.\n\n## Doramagic Pitfall Constraints\n\nThese rules come from Doramagic discovery, validation, or compilation pitfalls. The host AI must treat them as operating constraints, not general background notes.\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: do not present this pitfall as solved, verified, or safe to ignore unless later validation evidence explicitly closes it.\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: do not present this pitfall as solved, verified, or safe to ignore unless later validation evidence explicitly closes it.\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: do not present this pitfall as solved, verified, or safe to ignore unless later validation evidence explicitly closes it.\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: do not present this pitfall as solved, verified, or safe to ignore unless later validation evidence explicitly closes it.\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: do not present this pitfall as solved, verified, or safe to ignore unless later validation evidence explicitly closes it.\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: do not present this pitfall as solved, verified, or safe to ignore unless later validation evidence explicitly closes it.\n",
      "summary": "Context and operating boundaries for host AI agents.",
      "title": "AI Context Pack"
    },
    "boundary_risk_card": {
      "asset_id": "boundary_risk_card",
      "filename": "BOUNDARY_RISK_CARD.md",
      "markdown": "# Boundary & Risk Card\n\nProject: xingjianll/cyclic-agent\n\n## Doramagic Trial Decision\n\nCurrent decision: it can enter pre-publication recommendation checks. First use should still start with least privilege, a temporary directory, and reversible configuration.\n\n## What The User Can Do Now\n\n- Read the Human Manual first to understand the project purpose and main workflows.\n- Use Prompt Preview for pre-install exploration; it validates interaction shape, not real execution.\n- Run official Quick Start commands only inside an isolated environment, not a primary setup.\n\n## Do Not Do Yet\n\n- Do not treat Prompt Preview as a real project execution result.\n- Do not treat metadata-only validation as sandbox installation validation.\n- Do not describe unverified capabilities as supported, working, or safe to install.\n- Do not provide production data, private files, real secrets, or primary host configuration on first trial.\n\n## Pre-Install Checklist\n\n- Host AI match: local_cli\n- Official installation entry status: official entry point found\n- Isolated temporary directory, temporary host, or container validation: required\n- Configuration rollback path: required\n- API keys, network access, file access, or host configuration changes: treat as high risk until confirmed\n- Installation command, actual output, and failure logs: must be recorded\n\n## Current Blockers\n\n- review_required: community_discussion_evidence_below_public_threshold\n\n## Project-Specific Pitfalls\n\n- 能力判断依赖假设 (medium): 假设不成立时，用户拿不到承诺的能力。 Suggested check: 将假设转成下游验证清单。\n- 维护活跃度未知 (medium): 新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。 Suggested check: 补 GitHub 最近 commit、release、issue/PR 响应信号。\n- 下游验证发现风险项 (medium): 下游已经要求复核，不能在页面中弱化。 Suggested check: 进入安全/权限治理复核队列。\n- 存在评分风险 (medium): 风险会影响是否适合普通用户安装。 Suggested check: 把风险写入边界卡，并确认是否需要人工复核。\n- issue/PR 响应质量未知 (low): 用户无法判断遇到问题后是否有人维护。 Suggested check: 抽样最近 issue/PR，判断是否长期无人处理。\n\n## Risk And Permission Notes\n\n- no_demo: medium\n\n## Evidence Gaps\n\n- No structured evidence gaps are currently visible.\n",
      "summary": "Installation, permission, validation, and pre-recommendation risks.",
      "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 06:16:55 UTC\n\n## 目录\n\n- [Installation and Setup](#page-1)\n- [Project Overview](#page-2)\n- [State Base Class](#page-3)\n- [CyclicExecutor](#page-4)\n- [System Architecture](#page-5)\n- [Creating Custom States](#page-6)\n- [Memory Management with Fifo](#page-7)\n- [Hello World Example](#page-8)\n- [Bilibili Surfer Example](#page-9)\n- [Helper States](#page-10)\n\n<a id='page-1'></a>\n\n## Installation and Setup\n\n### 相关页面\n\n相关主题：[State Base Class](#page-3), [Hello World Example](#page-8)\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- [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# Installation and Setup\n\n## Overview\n\nCyclicAgent is a framework for creating LLM-powered, fully-autonomous AI agents using a finite state machine (FSM) architecture. The framework abstracts an agent as a collection of states that implement transition functions, allowing for cyclic execution patterns.\n\n资料来源：[README.md:1-8]()\n\n## Prerequisites\n\nBefore installing CyclicAgent, ensure your environment meets the following requirements:\n\n| Requirement | Minimum Version | Notes |\n|-------------|-----------------|-------|\n| Python | 3.10+ | Required for Pydantic v2 features |\n| pip | Latest recommended | For package installation |\n| LLM API Key | Provider-specific | Cohere, OpenAI, or similar |\n\n### Required Dependencies\n\nThe core dependencies include:\n\n- **Pydantic** - Base model and type validation\n- **Cohere SDK** or **OpenAI SDK** - For LLM integration\n- **python-dotenv** - For environment variable management\n\n资料来源：[cyclic_agent/state.py:1-4]()\n\n## Installation Methods\n\n### Standard Installation (Recommended)\n\nInstall the package directly from PyPI:\n\n```bash\npip install cyclic-agent\n```\n\n资料来源：[README.md:7-9]()\n\n### Development Installation\n\nFor contributing or modifying the source code:\n\n```bash\ngit clone https://github.com/xingjianll/cyclic-agent.git\ncd cyclic-agent\npip install -e .\n```\n\n### Dependencies in pyproject.toml\n\nThe package configuration specifies core dependencies for state management and LLM integration.\n\n资料来源：[pyproject.toml](https://github.com/xingjianll/cyclic-agent/blob/main/pyproject.toml)\n\n## Project Configuration\n\n### Environment Variables Setup\n\nCreate a `.env` file in your project root to store sensitive credentials:\n\n```bash\nCOHERE_API_KEY=your_api_key_here\n```\n\n#### Example .env Configuration\n\n```bash\n# LLM Configuration\nCOHERE_API_KEY=your_cohere_api_key\n\n# Platform-specific (for Bilibili example)\nSESSDATA=your_bilibili_sessdata\nBILI_JCT=your_bilibili_jct\nBUVID3=your_bilibili_buvid3\nNAME=your_name_for_bot_footers\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:1-20]()\n\n## Core Package Imports\n\nAfter installation, import the essential components:\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\n```\n\n资料来源：[cyclic_agent/__init__.py:1-6]()\n\n### Available Exports\n\n| Symbol | Type | Description |\n|--------|------|-------------|\n| `State` | Class | Abstract base class for all agent states |\n| `CyclicExecutor` | Class | Execution engine for running the state machine |\n\n## State Machine Architecture\n\nThe framework uses a state design pattern where each state implements a `next()` method returning the subsequent state.\n\n```mermaid\ngraph TD\n    A[Initial State] -->|next()| B[State 1]\n    B -->|next()| C[State 2]\n    C -->|next()| D[State N]\n    D -->|next()| A\n```\n\n资料来源：[README.md:10-16]()\n\n## Creating Your First Agent\n\n### Basic Setup Pattern\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\n资料来源：[examples/hello_world/hello_world.py:1-16]()\n\n### Implementing States\n\nEach state must inherit from `State` and implement the `next()` method:\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资料来源：[examples/hello_world/hello_world.py:18-24]()\n\n### State Base Class Requirements\n\nThe `State` class is a Pydantic `BaseModel` with an abstract method:\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-12]()\n\n## Running the Executor\n\n### Basic Execution\n\n```python\nif __name__ == \"__main__\":\n    initial_state = AskQuestion()\n    executor = CyclicExecutor(5)  # 5-second interval\n    executor.start(initial_state)\n    time.sleep(20)\n```\n\n资料来源：[examples/hello_world/hello_world.py:34-40]()\n\n### Executor Configuration\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `default_time_interval` | `float` | Required | Seconds between state transitions |\n| `running` | `bool` | `False` | Execution status |\n| `killed` | `bool` | `False` | Termination flag |\n\n资料来源：[cyclic_agent/executor.py:4-10]()\n\n### Executor Control Methods\n\n```mermaid\ngraph LR\n    A[start] --> B[running=True]\n    B --> C[_main_loop]\n    C --> D{state.next}\n    D --> E[time.sleep]\n    E --> C\n    F[pause] --> G[running=False]\n    H[resume] --> B\n    I[kill] --> J[killed=True]\n    J --> K[thread.join]\n```\n\nThe `CyclicExecutor` class provides thread-safe control:\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    def 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资料来源：[cyclic_agent/executor.py:4-25]()\n\n## Advanced Setup: Memory Integration\n\nFor agents requiring persistent memory, extend the base state class:\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:28-35]()\n\n### Memory Class Implementation\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\n资料来源：[examples/bilibili_surfer/fifo.py:1-14]()\n\n## Complete Project Structure\n\n```\ncyclic-agent/\n├── cyclic_agent/\n│   ├── __init__.py      # Package exports: State, CyclicExecutor\n│   ├── state.py         # State base class definition\n│   ├── executor.py      # CyclicExecutor implementation\n│   ├── cot.py           # Chain-of-thought state\n│   └── search.py        # Search state interface\n├── examples/\n│   ├── hello_world/     # Basic agent example\n│   └── bilibili_surfer/  # Complex multi-state example\n└── pyproject.toml       # Package configuration\n```\n\n## Verification Checklist\n\n- [ ] Python 3.10+ installed\n- [ ] `pip install cyclic-agent` completed successfully\n- [ ] `.env` file created with required API keys\n- [ ] `from cyclic_agent import State, CyclicExecutor` imports without errors\n- [ ] Basic state class compiles correctly\n- [ ] Executor starts without exceptions\n\n## Troubleshooting Common Setup Issues\n\n| Issue | Solution |\n|-------|----------|\n| ImportError for State | Ensure `from __future__ import annotations` is present |\n| Type validation errors | Use `model_config = ConfigDict(arbitrary_types_allowed=True)` |\n| Threading issues | Executor methods are thread-safe via locks |\n| Forward reference errors | Use `from __future__ import annotations` at file top |\n\n资料来源：[cyclic_agent/state.py:1-2](), [examples/bilibili_surfer/bilibili_surfer.py:30]()\n\n---\n\n<a id='page-2'></a>\n\n## Project Overview\n\n### 相关页面\n\n相关主题：[State Base Class](#page-3), [CyclicExecutor](#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/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/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- [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- [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</details>\n\n# Project Overview\n\n## Introduction\n\nCyclicAgent is a Python framework designed for creating **LLM-powered, fully-autonomous AI agents**. It provides a clean abstraction for building AI systems that can continuously operate by modeling agent behavior as a finite state machine (FSM). 资料来源：[README.md:1]()\n\nThe framework enables developers to define AI behavior through a state design pattern, where each state represents a distinct behavior or action the agent can perform. States transition to one another based on internal attributes (such as memory and meta prompts) as well as external signals, creating a cyclic execution model that can run indefinitely. 资料来源：[README.md:6-9]()\n\n## Core Design Philosophy\n\nCyclicAgent abstracts an agent as a **finite state machine (FSM)** using the state design pattern. This approach offers several advantages:\n\n| Benefit | Description |\n|---------|-------------|\n| **Modularity** | Each behavior is encapsulated in its own state class |\n| **Scalability** | New states can be added without modifying existing ones |\n| **Predictability** | State transitions follow defined rules |\n| **Testability** | Individual states can be tested in isolation |\n| **Extensibility** | The framework supports custom state types and transitions |\n\n资料来源：[README.md:6-9]()\n\n### State Transition Model\n\nThe fundamental principle of CyclicAgent is that **all states implement a state transition function**, which returns another state. This allows for chaining transition operations indefinitely, making the agent \"Cyclic\". 资料来源：[README.md:10-11]()\n\n```mermaid\ngraph TD\n    A[Initial State] -->|next()| B[State 1]\n    B -->|next()| C[State 2]\n    C -->|next()| D[State 3]\n    D -->|next()| B\n    E[External Signal] -.->|signal| C\n```\n\n## Architecture\n\n### System Components\n\nCyclicAgent consists of the following core components:\n\n| Component | File | Purpose |\n|-----------|------|---------|\n| `State` | `cyclic_agent/state.py` | Abstract base class for all agent states |\n| `CyclicExecutor` | `cyclic_agent/executor.py` | Manages the execution loop of states |\n| `Search` | `cyclic_agent/search.py` | Specialized state for search operations |\n| `CoT` | `cyclic_agent/cot.py` | Chain-of-thought reasoning state |\n\n资料来源：[cyclic_agent/__init__.py:1-6]()\n\n### Class Hierarchy\n\n```mermaid\nclassDiagram\n    class State~SigT~ {\n        <<abstract>>\n        +next(signal) State\n    }\n    class CyclicExecutor {\n        -running: bool\n        -default_time_interval: float\n        +start(initial_state)\n        +pause()\n        +resume()\n        +kill()\n    }\n    class Search {\n        +query: str\n        +exit_: Callable\n        +search(query) str\n    }\n    class CoT {\n        +exit_: Callable\n        +llm: State\n        +prompt: str\n    }\n    State <|-- Search\n    State <|-- CoT\n```\n\n## Core Components\n\n### State Base Class\n\nThe `State` class is the foundation of the framework. It is a **generic abstract base class** built on Pydantic's `BaseModel`, providing type safety and data validation. 资料来源：[cyclic_agent/state.py:1-13]()\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**Key Features:**\n- **Generic Type Parameter**: `SigT` represents the signal type for state transitions\n- **Pydantic Integration**: Enables automatic data validation and serialization\n- **Abstract Method**: `next()` must be implemented by all concrete states\n\n资料来源：[cyclic_agent/state.py:1-13]()\n\n### CyclicExecutor\n\nThe `CyclicExecutor` is responsible for running the state machine in a separate thread. It manages the execution lifecycle including start, pause, resume, and kill operations. 资料来源：[cyclic_agent/executor.py:1-45]()\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| Parameter | Type | Description |\n|-----------|------|-------------|\n| `default_time_interval` | `float` | Sleep duration (seconds) between state transitions |\n| `running` | `bool` | Flag indicating if executor is actively running |\n| `killed` | `bool` | Flag indicating if executor has been terminated |\n\n**Execution Flow:**\n\n```mermaid\ngraph TD\n    A[Start] --> B{running?}\n    B -->|Yes| C[state = state.next()]\n    B -->|No| D[Wait]\n    C --> E[Sleep for interval]\n    E --> B\n    D --> B\n    F[Kill Signal] --> G[killed = True]\n    G --> H[Exit Loop]\n```\n\n资料来源：[cyclic_agent/executor.py:1-45]()\n\n## State Implementation Patterns\n\n### Simple State Pattern\n\nStates are implemented by extending the `State` class and implementing the `next()` method. Each state returns the next state to transition to. 资料来源：[examples/hello_world/hello_world.py:1-38]()\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```\n\n**Transition Diagram:**\n\n```mermaid\ngraph LR\n    A[AskQuestion] -->|next()| B[AnswerQuestion]\n    B -->|next()| A\n```\n\n### State with Memory Pattern\n\nAdvanced states can maintain memory to track past actions and decisions. The Bilibili Surfer example demonstrates this pattern using a FIFO (First-In-First-Out) queue. 资料来源：[examples/bilibili_surfer/fifo.py:1-27]()\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| Attribute | Type | Purpose |\n|-----------|------|---------|\n| `initial_prompt` | `str` | Base prompt for LLM interactions |\n| `memory` | `Fifo` | Queue storing past agent actions |\n| `co` | `Client` | Cohere LLM client instance |\n| `credential` | `Credential` | Authentication credentials |\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:1-55]()\n\n### State Inference Pattern\n\nStates can use LLM-driven inference to determine the next state dynamically:\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资料来源：[examples/bilibili_surfer/bilibili_surfer.py:28-43]()\n\n## Memory System\n\n### FIFO Queue Implementation\n\nThe framework includes a `Fifo` class for maintaining conversation history and action logs:\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| Feature | Description |\n|---------|-------------|\n| `capacity` | Maximum number of items (default: 100) |\n| `queue` | List storing items with timestamps |\n| `log_file` | Persistent log file for audit trail |\n\n**Behavior:**\n- When capacity is reached, the oldest item is automatically removed\n- Each item is timestamped and logged to file\n- The `prompt()` method returns items in reverse chronological order\n\n资料来源：[examples/bilibili_surfer/fifo.py:1-27]()\n\n## Specialized States\n\n### Search State\n\nA generic search state that executes queries and transitions based on results:\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-14]()\n\n### Chain-of-Thought State\n\nEnables step-by-step reasoning by appending \"Let's think step by step.\" to prompts:\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        return self.llm(prompt=prompt, callback=self.exit_)\n```\n\n资料来源：[cyclic_agent/cot.py:1-15]()\n\n## Complete Workflow Example\n\nThe Bilibili Surfer demonstrates a complete autonomous agent workflow:\n\n```mermaid\ngraph TD\n    A[BrowsingVideo] -->|search videos| B[Display Top 10 Videos]\n    B --> C{Select Video}\n    C -->|browse| D[ReadingComments]\n    D -->|view comments| E{Choose Action}\n    E -->|reply| F[PostComment]\n    E -->|continue| D\n    F -->|done| A\n    D -->|back| A\n```\n\n**State Transitions:**\n\n| Current State | Next State(s) | Trigger |\n|---------------|---------------|---------|\n| `BrowsingVideo` | `BrowsingVideo`, `ReadingComments` | LLM inference |\n| `ReadingComments` | `BrowsingVideo`, `ReadingComments`, `PostComment` | LLM inference |\n| `PostComment` | `BrowsingVideo` | Comment posted |\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:1-180]()\n\n## Package Exports\n\nThe framework exposes a minimal public API:\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\n```\n\nAll core functionality is accessible through these two classes, keeping the API simple and intuitive for developers. 资料来源：[cyclic_agent/__init__.py:1-6]()\n\n## Installation\n\nInstall the framework via pip:\n\n```shell\npip install cyclic-agent\n```\n\nThe package is available on PyPI and can be integrated into any Python project. 资料来源：[README.md:4-6]()\n\n## Requirements\n\n- Python 3.10+ (for generic syntax support)\n- Pydantic for data validation\n- `from __future__ import annotations` may be needed for forward references in some Python versions 资料来源：[README.md:28]()\n\n## Summary\n\nCyclicAgent provides a clean, Pythonic way to build autonomous AI agents using the finite state machine pattern. Its key strengths include:\n\n1. **Simple Core API**: Only two main classes (`State` and `CyclicExecutor`) needed for basic usage\n2. **Flexible State Definition**: States are Pydantic models with type safety\n3. **Memory Integration**: Built-in support for FIFO queues and action logging\n4. **Thread-Safe Execution**: Concurrent execution with pause/resume/kill controls\n5. **Extensible Design**: Custom state types can be created by extending the base class\n\nThe framework is well-suited for building autonomous agents that need to make decisions, maintain context, and perform actions in a continuous loop.\n\n---\n\n<a id='page-3'></a>\n\n## State Base Class\n\n### 相关页面\n\n相关主题：[CyclicExecutor](#page-4), [Creating Custom States](#page-6)\n\n<details>\n<summary>Relevant Source Files</summary>\n\n以下源码文件用于生成本页说明：\n\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/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 Base Class\n\n## Overview\n\nThe `State` class is the foundational abstraction in CyclicAgent, implementing the **State Design Pattern** to model agents as finite state machines (FSM). Every agent behavior is encapsulated as a state that can transition to another state through the `next()` method.\n\n**Core Design Principle:** States implement a transition function that returns another state, enabling indefinite chaining and creating the \"cyclic\" nature of the agent framework.\n\n资料来源：[cyclic_agent/state.py:6-9]()\n\n---\n\n## Architecture\n\n### Class Definition\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| Property | Description |\n|----------|-------------|\n| Generic Parameter `SigT` | Signal type for external communication between states |\n| Base Class | Pydantic `BaseModel` for data validation and serialization |\n| Abstract Method `next()` | Must be implemented by subclasses to define state transitions |\n\n资料来源：[cyclic_agent/state.py:6-9]()\n\n### Generic Type Parameter `SigT`\n\nThe `SigT` generic parameter defines the type of signal an external entity can send to influence state transitions:\n\n| Signal Type | Use Case |\n|-------------|----------|\n| `State[None]` | Autonomous states with no external input |\n| `State[str]` | States that receive string-based signals |\n| `State[Any]` | States accepting any signal type |\n\n资料来源：[cyclic_agent/state.py:6]()\n\n### Relationship with CyclicExecutor\n\n```mermaid\ngraph TD\n    A[Initial State] -->|next()| B[State B]\n    B -->|next()| C[State C]\n    C -->|next()| A\n    D[CyclicExecutor] -->|controls| E[Running Loop]\n    E -->|calls next()| A\n    E -->|calls next()| B\n    E -->|calls next()| C\n```\n\nThe `CyclicExecutor` runs a continuous loop that repeatedly calls `next()` on the current state, enabling cyclic transitions.\n\n资料来源：[cyclic_agent/executor.py:28-33]()\n\n---\n\n## Implementation Patterns\n\n### Pattern 1: Simple Two-State Cyclic Agent\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\nimport cohere\n\nclass AskQuestion(State[None]):\n    def next(self, signal: None = None) -> AnswerQuestion:\n        response = cohere.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 = cohere.chat(message=self.question)\n        return AskQuestion()\n```\n\n资料来源：[examples/hello_world/hello_world.py:10-24]()\n\n### Pattern 2: State with Context Attributes\n\nStates inherit from `BaseModel`, allowing Pydantic field definitions for context:\n\n```python\nclass AnswerQuestion(State[None]):\n    question: str  # Context attribute persisted across transitions\n\n    def next(self, signal: None = None) -> AskQuestion:\n        answer = cohere.chat(message=self.question)\n        return AskQuestion()\n```\n\n资料来源：[examples/hello_world/hello_world.py:19-24]()\n\n### Pattern 3: Complex State with Type Unions\n\nDefine reachable states using Python type unions for type-safe transitions:\n\n```python\ntype BrowsingVideoReachable = Union[BrowsingVideo, ReadingComments]\n\n\nclass BrowsingVideo(BilibiliStateBase):\n    @overrides\n    def next(self, signal: None = None) -> BrowsingVideoReachable:\n        # ... logic ...\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资料来源：[examples/bilibili_surfer/bilibili_surfer.py:1-85]()\n\n---\n\n## State Machine Design\n\n### Transition Flow\n\n```mermaid\ngraph LR\n    S1[State 1] -->|next() returns State 2| S2[State 2]\n    S2 -->|next() returns State 3| S3[State 3]\n    S3 -->|next() returns State 1| S1\n```\n\nEach state transition:\n1. Receives optional `signal` parameter\n2. Executes state-specific logic\n3. Returns the next state instance\n4. Context (fields) can be preserved or replaced\n\n### Base Class Requirements\n\n| Requirement | Implementation |\n|-------------|----------------|\n| Inherit from `State[SigT]` | Provides FSM contract |\n| Implement `next()` | Defines transition logic |\n| Use `from __future__ import annotations` | Required for forward references |\n\n资料来源：[examples/hello_world/hello_world.py:1-3]()\n\n---\n\n## Advanced Usage: Abstract Base State\n\nFor complex applications, create an abstract base state with shared functionality:\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        \"\"\"Helper method for LLM-driven state inference.\"\"\"\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            \"\"\"\n        )\n        return self.co.chat(temperature=1, message=prompt).text\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:25-40]()\n\n---\n\n## Integration with CyclicExecutor\n\n| Executor Method | State Interaction |\n|-----------------|-------------------|\n| `start(initial_state)` | Begins execution with starting state |\n| `_main_loop(state)` | Calls `state.next()` in loop |\n| `pause()` / `resume()` | Controls execution flow |\n| `kill()` | Stops execution permanently |\n\n```python\nclass CyclicExecutor:\n    def _main_loop(self, state: State) -> None:\n        while True:\n            if self.killed:\n                return\n            if self.running:\n                state = state.next()  # State transition\n                time.sleep(self.default_time_interval)\n```\n\n资料来源：[cyclic_agent/executor.py:28-33]()\n\n---\n\n## Export and Import\n\nThe `State` class is exported from the package root:\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\n```\n\n资料来源：[cyclic_agent/__init__.py:1-4]()\n\n---\n\n## Summary\n\n| Aspect | Description |\n|--------|-------------|\n| **Purpose** | Base class for all agent states in FSM architecture |\n| **Base** | Pydantic `BaseModel` |\n| **Generic** | `State[SigT]` for signal type parameterization |\n| **Key Method** | `next(signal)` returns next state |\n| **Usage** | Inherit and implement `next()` for state behavior |\n\n---\n\n<a id='page-4'></a>\n\n## CyclicExecutor\n\n### 相关页面\n\n相关主题：[State Base Class](#page-3), [Creating Custom States](#page-6), [Helper States](#page-10)\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- [README.md](https://github.com/xingjianll/cyclic-agent/blob/main/README.md)\n</details>\n\n# CyclicExecutor\n\n## Overview\n\nCyclicExecutor is the core execution engine in the CyclicAgent framework. It manages the continuous execution loop that drives the finite state machine (FSM) pattern implemented by agents. The executor handles state transitions, threading, and timing control for autonomous agent behavior.\n\n**Purpose:** The CyclicExecutor provides a runtime environment for executing state machines where each state can transition to another state indefinitely, enabling fully autonomous AI agents.\n\n**Scope:** It abstracts away the complexity of thread management, timing, and execution flow, allowing developers to focus purely on defining state behavior.\n\n资料来源：[cyclic_agent/executor.py:1-34]()\n\n## Architecture\n\n### Design Pattern\n\nCyclicExecutor implements the **State Design Pattern** where agents are represented as finite state machines. Each state implements a `next()` method that returns the subsequent state, creating an unbounded chain of transitions.\n\n```mermaid\ngraph TD\n    A[Initial State] -->|next()| B[State 1]\n    B -->|next()| C[State 2]\n    C -->|next()| D[State N]\n    D -->|next()| A\n    D -->|next()| B\n```\n\n### Class Structure\n\n| Component | Type | Description |\n|-----------|------|-------------|\n| `running` | `bool` | Flag indicating if executor is active |\n| `killed` | `bool` | Flag indicating permanent shutdown |\n| `lock` | `threading.Lock` | Thread synchronization primitive |\n| `thread` | `threading.Thread` | Background execution thread |\n| `default_time_interval` | `float` | Sleep duration between state transitions |\n\n资料来源：[cyclic_agent/executor.py:7-14]()\n\n## API Reference\n\n### Constructor\n\n```python\ndef __init__(self, default_time_interval: float)\n```\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `default_time_interval` | `float` | required | Seconds to sleep between each state transition |\n\n### Methods\n\n#### `start(initial_state: State) -> None`\n\nInitiates the executor in a new background thread. The executor begins calling `state.next()` repeatedly, transitioning through states at intervals defined by `default_time_interval`.\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `initial_state` | `State[SigT]` | The starting state of the FSM |\n\n```python\nexecutor = CyclicExecutor(5)\nexecutor.start(initial_state)\n```\n\n#### `pause() -> None`\n\nTemporarily halts execution without terminating the thread. The thread remains alive but the main loop skips state transitions.\n\n#### `resume() -> None`\n\nResumes execution after a pause. State transitions continue from the current state.\n\n#### `kill() -> None`\n\nPermanently stops the executor and joins the thread. Sets `killed` flag to `True` ensuring the main loop terminates cleanly.\n\n```python\nexecutor.kill()  # Clean shutdown\n```\n\n资料来源：[cyclic_agent/executor.py:16-31]()\n\n## Execution Flow\n\n### Main Loop Logic\n\n```mermaid\nflowchart TD\n    A[_main_loop started] --> B{killed?}\n    B -->|Yes| Z[Return]\n    B -->|No| C{running?}\n    C -->|No| D[Sleep default_time_interval]\n    D --> B\n    C -->|Yes| E[state = state.next()]\n    E --> F[Sleep default_time_interval]\n    F --> B\n```\n\nThe `_main_loop` method runs in a dedicated thread and performs the following operations:\n\n1. Check `killed` flag; exit if `True`\n2. Check `running` flag; skip transition if `False`\n3. Call `state.next()` to get the next state\n4. Sleep for `default_time_interval` seconds\n5. Repeat\n\n资料来源：[cyclic_agent/executor.py:33-35]()\n\n### Thread Safety\n\nThe executor uses a `threading.Lock` to protect shared state modifications:\n\n```python\nself.lock = threading.Lock()\n\ndef pause(self):\n    with self.lock:\n        self.running = False\n```\n\nAll state modifications (`start`, `pause`, `resume`, `kill`) acquire the lock before modifying `running` or `killed` flags.\n\n资料来源：[cyclic_agent/executor.py:10]()\n\n## State Integration\n\n### State Base Class\n\nThe executor expects states to implement the `State[SigT]` protocol:\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\nStates are Pydantic models, enabling automatic serialization and validation of state data.\n\n资料来源：[cyclic_agent/state.py:6-9]()\n\n### Type Parameter Usage\n\nThe generic type `SigT` allows states to receive external signals of any type:\n\n| Type Parameter | Signal Type | Usage |\n|----------------|--------------|-------|\n| `State[None]` | No signal | Simple autonomous agents |\n| `State[str]` | String messages | Interactive agents |\n| `State[dict]` | Structured data | Data-driven agents |\n\n资料来源：[cyclic_agent/state.py:6]()\n\n## Configuration Options\n\n| Option | Value Type | Default | Effect |\n|--------|------------|---------|--------|\n| `default_time_interval` | `float` | Required | Controls execution speed; lower = faster transitions |\n| Thread spawning | Automatic | - | Creates daemon thread on `start()` |\n| Signal handling | Passive | - | No signal handling implemented |\n\n### Interval Selection Guidelines\n\n| Interval Range | Use Case |\n|----------------|----------|\n| `0.1 - 1.0` | Fast response scenarios, API polling |\n| `1.0 - 5.0` | Balanced interaction, LLM response times |\n| `5.0 - 60.0` | Slow operations, external API rate limits |\n\n资料来源：[cyclic_agent/executor.py:12]()\n\n## Usage Examples\n\n### Basic Hello World\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\", temperature=1)\n        return AnswerQuestion(question=response.text)\n\nclass AnswerQuestion(State[None]):\n    question: str\n    \n    def next(self, signal=None) -> AskQuestion:\n        answer = co.chat(message=self.question)\n        return AskQuestion()\n\n# Initialize and run\nexecutor = CyclicExecutor(5)  # 5-second intervals\nexecutor.start(AskQuestion())\ntime.sleep(20)\nexecutor.kill()\n```\n\n资料来源：[examples/hello_world/hello_world.py:1-26]()\n\n### Complex Agent: Bilibili Surfer\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\n\nclass BrowsingVideo(BilibiliStateBase):\n    @overrides\n    def next(self, signal=None) -> BrowsingVideoReachable:\n        # Search and select video\n        response = self.co.chat(temperature=1, message=prompt).text\n        video = res['result'][int(response)]\n        \n        # Return next state based on decision\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资料来源：[examples/bilibili_surfer/bilibili_surfer.py:1-95]()\n\n### Typical Execution Pattern\n\n```mermaid\nsequenceDiagram\n    participant Main as Main Thread\n    participant Executor as CyclicExecutor\n    participant State as Current State\n    \n    Main->>Executor: start(initial_state)\n    Executor->>Executor: Create Thread\n    \n    loop Every default_time_interval seconds\n        Executor->>State: state.next()\n        State-->>Executor: Next State\n        Executor->>State: Update state reference\n    end\n    \n    Main->>Executor: kill()\n    Executor->>Executor: Set killed=True\n    Executor->>Main: Thread joins\n```\n\n## Exports\n\nCyclicExecutor is exported from the main package:\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\n```\n\n```python\n__all__ = [\"State\", \"CyclicExecutor\"]\n```\n\n资料来源：[cyclic_agent/__init__.py:1-6]()\n\n## Limitations\n\n- **Daemon Thread:** The execution thread is a daemon thread, meaning it won't prevent the Python process from exiting\n- **No Signal Handling:** External signals cannot interrupt the execution loop\n- **No State Persistence:** States are not persisted between sessions\n- **Single Thread:** Only one thread executes states; no parallel state machines\n\n资料来源：[cyclic_agent/executor.py:18]()\n\n## Related Components\n\n| Component | File | Relationship |\n|-----------|------|--------------|\n| `State` | `cyclic_agent/state.py` | Base class for states |\n| `Search` | `cyclic_agent/search.py` | Generic search state |\n| `CoT` | `cyclic_agent/cot.py` | Chain-of-thought state |\n| `Fifo` | `examples/bilibili_surfer/fifo.py` | Memory for states |\n\n资料来源：[cyclic_agent/search.py:1-14](), [cyclic_agent/cot.py:1-18](), [examples/bilibili_surfer/fifo.py:1-30]()\n\n---\n\n<a id='page-5'></a>\n\n## System Architecture\n\n### 相关页面\n\n相关主题：[State Base Class](#page-3), [CyclicExecutor](#page-4), [Memory Management with Fifo](#page-7)\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/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# System Architecture\n\n## Overview\n\nCyclicAgent is a framework for building autonomous AI agents based on the **Finite State Machine (FSM)** design pattern. The architecture abstracts an agent as a collection of states, where each state implements a transition function that returns another state, enabling cyclic execution flows. 资料来源：[README.md:9]()\n\nThe system is designed to handle autonomous workflows where agents can:\n\n- Maintain internal state (memory, prompts)\n- Respond to external signals\n- Transition between states infinitely\n- Interact with external environments (APIs, platforms)\n\n## Core Design Principles\n\n### State Pattern Implementation\n\nThe architecture uses Python's generic type syntax (PEP 695) combined with Pydantic for state modeling. Each state is a Pydantic model that encapsulates both data and behavior. 资料来源：[cyclic_agent/state.py:8]()\n\n### Key Characteristics\n\n| Characteristic | Description |\n|----------------|-------------|\n| **Type Safety** | Generic type parameters enable compile-time checking |\n| **Serialization** | Pydantic BaseModel provides automatic serialization |\n| **Extensibility** | Abstract base allows custom state implementations |\n| **Thread Safety** | Executor uses locks for safe concurrent operation |\n\n## Architecture Components\n\n### State Base Class\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\nThe `State` class serves as the foundation for all agent states:\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `SigT` | Generic | Signal type for state transitions |\n| `next()` | Method | Abstract transition function returning next state |\n| `signal` | Parameter | Optional external signal influencing transition |\n\n资料来源：[cyclic_agent/state.py:7-11]()\n\n### CyclicExecutor\n\nThe `CyclicExecutor` manages the runtime execution loop for state machines:\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| Method | Description |\n|--------|-------------|\n| `start(initial_state)` | Initiates the execution loop in a separate thread |\n| `pause()` | Halts execution without terminating |\n| `resume()` | Continues execution from paused state |\n| `kill()` | Stops the executor and joins the thread |\n\n资料来源：[cyclic_agent/executor.py:1-29]()\n\n## Execution Flow\n\n```mermaid\ngraph TD\n    A[Start: CyclicExecutor.start] --> B{self.running?}\n    B -->|Yes| C[state = state.next]\n    B -->|No| D[Wait]\n    C --> E[Sleep: default_time_interval]\n    E --> B\n    D --> B\n    F[Kill Signal] --> G[self.killed = True]\n    G --> B\n    B -->|self.killed| H[Exit Loop]\n```\n\nThe main loop continuously calls `state.next()` and sleeps for the configured interval. Thread safety is maintained through a lock that guards the `running` and `killed` flags. 资料来源：[cyclic_agent/executor.py:27-33]()\n\n## State Machine Structure\n\n### Typical State Implementation\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\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\nEach state class:\n1. Inherits from `State[SignalType]`\n2. Stores relevant data as Pydantic fields\n3. Implements `next()` returning the next state instance\n\n资料来源：[examples/hello_world/hello_world.py:13-26]()\n\n### State Transitions\n\n```mermaid\ngraph LR\n    A[AskQuestion] -->|next()| B[AnswerQuestion]\n    B -->|next()| A\n```\n\nThe cyclic nature allows indefinite chaining of states, enabling continuous autonomous operation. 资料来源：[README.md:27-42]()\n\n## Supporting Components\n\n### Memory Management (Fifo)\n\nThe `Fifo` class provides persistent memory for states:\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| Feature | Description |\n|---------|-------------|\n| `capacity` | Maximum stored items (default: 100) |\n| `add(item)` | Adds item with timestamp, auto-evicts oldest |\n| `prompt()` | Returns formatted history string |\n| Logging | All additions logged to file with timestamps |\n\n资料来源：[examples/bilibili_surfer/fifo.py:1-27]()\n\n### Base State Pattern\n\nComplex states inherit from a base class providing common functionality:\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        # LLM-based state inference logic\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:25-44]()\n\n## Advanced State Patterns\n\n### Chain of Thought (CoT)\n\nThe framework includes a `CoT` state for step-by-step reasoning:\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### Search State\n\nThe `Search` state provides a template for search operations:\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-16]()\n\n## Complex State Machine Example\n\nThe Bilibili Surfer example demonstrates a multi-state architecture:\n\n```mermaid\ngraph TD\n    A[BrowsingVideo] -->|next| B[ReadingComments]\n    A -->|next| A\n    B -->|next| C[PostComment]\n    B -->|next| A\n    C -->|next| A\n```\n\n| State | Purpose | Reachable States |\n|-------|---------|------------------|\n| `BrowsingVideo` | Search and select videos | `BrowsingVideo`, `ReadingComments` |\n| `ReadingComments` | View and select comments | `BrowsingVideo`, `ReadingComments`, `PostComment` |\n| `PostComment` | Reply to selected comment | `BrowsingVideo` |\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:60-130]()\n\n## Configuration and Threading\n\n### Executor Threading Model\n\n```mermaid\ngraph TD\n    subgraph MainThread\n        A[CyclicExecutor.start]\n    end\n    subgraph WorkerThread\n        B[_main_loop]\n        C[state.next]\n        D[time.sleep]\n    end\n    A -->|spawns| B\n    B --> C\n    C --> D\n    D --> B\n```\n\nThe executor spawns a dedicated thread for the main loop, ensuring non-blocking operation. The lock ensures safe modification of `running` and `killed` flags from external threads. 资料来源：[cyclic_agent/executor.py:16-18]()\n\n### Time Interval Configuration\n\n```python\nexecutor = CyclicExecutor(5)  # 5-second interval between state transitions\nexecutor.start(initial_state)\ntime.sleep(20)  # Main thread sleeps while executor runs\n```\n\nThe `default_time_interval` parameter controls the delay between state transitions, allowing rate limiting and API compliance. 资料来源：[examples/hello_world/hello_world.py:28-32]()\n\n## Summary\n\nThe CyclicAgent architecture provides:\n\n1. **State Pattern Foundation** - Generic, type-safe state classes with Pydantic\n2. **Cyclic Execution** - Infinite state transitions enabling autonomous agents\n3. **Thread-Safe Execution** - Lock-protected executor with pause/resume/kill controls\n4. **Memory Persistence** - FIFO-based history with file logging\n5. **Extensibility** - Abstract base classes for custom state implementations\n\nThe framework's simplicity—combining a base `State` class with an `Executor`—enables complex autonomous behaviors through composition of simple state transitions.\n\n---\n\n<a id='page-6'></a>\n\n## Creating Custom States\n\n### 相关页面\n\n相关主题：[State Base Class](#page-3), [Hello World Example](#page-8), [Bilibili Surfer Example](#page-9)\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- [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/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# Creating Custom States\n\n## Overview\n\nIn CyclicAgent, **states** are the fundamental building blocks of autonomous agents. Each state represents a distinct behavior or step in an agent's workflow, and states transition to one another through a well-defined interface. This design pattern enables the creation of complex, cyclic agent behaviors where execution can loop indefinitely through different states.\n\nThe framework abstracts an agent as a **finite state machine (FSM)** using the state design pattern. Each state implements a `next()` method that returns another state, creating an infinite transition chain that makes the agent \"cyclic.\" 资料来源：[README.md:12-14]()\n\n## Architecture\n\n### State Pattern Design\n\nThe `State` class serves as the abstract base for all agent states. It leverages Python's generic type system to provide type safety for signals passed between states.\n\n```mermaid\ngraph TD\n    A[State SigT] -->|extends| B[AskQuestion]\n    A -->|extends| C[AnswerQuestion]\n    A -->|extends| D[CustomState]\n    B -->|next() returns| C\n    C -->|next() returns| B\n    D -->|next() returns| E[NextState]\n```\n\n### Key Components\n\n| Component | File | Purpose |\n|-----------|------|---------|\n| `State[SigT]` | `cyclic_agent/state.py` | Abstract base class for all states |\n| `CyclicExecutor` | `cyclic_agent/executor.py` | Executes the state machine loop |\n| `CyclicExecutor.start()` | `cyclic_agent/executor.py` | Initiates the state machine |\n\n## Creating Basic States\n\n### Step 1: Define Your State Class\n\nExtend the `State` class and implement the `next()` method:\n\n```python\nfrom __future__ import annotations\nfrom cyclic_agent import State, CyclicExecutor\n\nclass MyState(State[None]):\n    def next(self, signal: None = None) -> AnotherState:\n        # Perform state actions\n        return AnotherState()\n```\n\n### Step 2: Implement State Logic\n\nThe `next()` method should contain the logic for the current state and return the next state to transition to:\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资料来源：[examples/hello_world/hello_world.py:14-18]()\n\n### Step 3: Create the State Transition Pair\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资料来源：[examples/hello_world/hello_world.py:21-26]()\n\n### Step 4: Execute the State Machine\n\n```python\nif __name__ == \"__main__\":\n    initial_state = AskQuestion()\n    executor = CyclicExecutor(5)  # 5-second interval between transitions\n    executor.start(initial_state)\n```\n\n资料来源：[examples/hello_world/hello_world.py:29-33]()\n\n## State API Reference\n\n### State Class\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:1-9]()\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `signal` | `SigT \\| None` | Optional signal passed to the state for external input |\n| **Returns** | `State[SigT]` | The next state in the transition chain |\n\n### State Data Model\n\nStates inherit from Pydantic's `BaseModel`, providing automatic validation and serialization:\n\n```python\nclass AnswerQuestion(State[None]):\n    question: str  # State-specific attribute\n```\n\n资料来源：[examples/hello_world/hello_world.py:20-21]()\n\n## CyclicExecutor\n\n### Execution Model\n\nThe `CyclicExecutor` runs the state machine in a background thread, transitioning between states at configurable intervals.\n\n```mermaid\ngraph TD\n    A[Start] --> B{self.running?}\n    B -->|Yes| C[state = state.next()]\n    B -->|No| D[Wait...]\n    C --> E[Sleep interval]\n    E --> B\n    D --> B\n    F[Kill] --> G[Exit loop]\n```\n\n### CyclicExecutor API\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:6-12]()\n\n| Method | Description |\n|--------|-------------|\n| `start(initial_state)` | Start execution with an initial state |\n| `pause()` | Pause the state machine |\n| `resume()` | Resume from pause |\n| `kill()` | Stop execution completely |\n\n### Thread Safety\n\nThe executor uses a threading lock to ensure thread-safe state transitions:\n\n```python\ndef pause(self):\n    with self.lock:\n        self.running = False\n```\n\n资料来源：[cyclic_agent/executor.py:27-29]()\n\n## Advanced State Patterns\n\n### States with Memory\n\nComplex agents often need to remember past actions. States can include memory components:\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:16-22]()\n\n### FIFO Memory Implementation\n\n```python\nclass Fifo:\n    def __init__(self):\n        self.capacity = 100\n        self.queue = []\n\n    def add(self, item):\n        if len(self.queue) >= self.capacity:\n            self.queue.pop(0)\n        self.queue.append(item)\n\n    def prompt(self):\n        return \"\\n\".join([f\"{time} - {text}\" for text, time in reversed(self.queue)])\n```\n\n资料来源：[examples/bilibili_surfer/fifo.py:1-19]()\n\n### State-Independent Transitions\n\nStates can transition to different next states based on internal logic using pattern matching:\n\n```python\nmatch 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:58-63]()\n\n### State Inference Helper\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        \"\"\"\n    )\n    text = self.co.chat(temperature=1, message=prompt).text\n    return text\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:25-36]()\n\n## Type Aliases for State Transitions\n\nCyclicAgent uses Python type aliases to define valid state transitions, enabling static type checking:\n\n```python\ntype BrowsingVideoReachable = Union[BrowsingVideo, ReadingComments]\ntype ReadingCommentsReachable = Union[BrowsingVideo, ReadingComments, PostComment]\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:13-14]()\n\n## Complete Example: Two-State Loop\n\n```python\nfrom __future__ import annotations\nimport os\nimport time\nimport cohere\nfrom dotenv import load_dotenv\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资料来源：[examples/hello_world/hello_world.py:1-33]()\n\n## Best Practices\n\n### Forward References\n\nAlways use `from __future__ import annotations` for forward references in type hints:\n\n```python\nfrom __future__ import annotations\n```\n\n### State Immutability\n\nReturn new state instances rather than modifying existing ones to ensure thread safety:\n\n```python\ndef next(self, signal: None = None) -> AskQuestion:\n    return AskQuestion()  # Return new instance\n```\n\n### Signal Usage\n\nLeverage the signal parameter for external state control:\n\n```python\nclass ControlledState(State[str]):\n    def next(self, signal: str | None = None) -> State:\n        if signal == \"exit\":\n            return ExitState()\n        return AnotherState()\n```\n\n### Pydantic Configuration\n\nUse `ConfigDict(arbitrary_types_allowed=True)` when states contain non-Pydantic types like external clients or credentials:\n\n```python\nmodel_config = ConfigDict(arbitrary_types_allowed=True)\n```\n\n## Execution Flow\n\n```mermaid\nsequenceDiagram\n    participant User\n    participant Executor\n    participant State1\n    participant State2\n    \n    User->>Executor: start(AskQuestion)\n    Executor->>State1: next()\n    State1-->>Executor: AnswerQuestion\n    Executor->>State2: next()\n    State2-->>Executor: AskQuestion\n    Executor->>State1: next()\n    Note over Executor: Loop continues...\n```\n\n## Summary\n\nCreating custom states in CyclicAgent involves:\n\n1. **Extending** `State[SigT]` with your state class\n2. **Implementing** the `next()` method with state logic and transitions\n3. **Using** Pydantic for data model attributes\n4. **Executing** through `CyclicExecutor` with configurable intervals\n5. **Leveraging** memory and state inference for complex behaviors\n\nThe state pattern enables modular, maintainable agent design where each state is independent and transitions are explicit, making the agent behavior predictable and debuggable.\n\n---\n\n<a id='page-7'></a>\n\n## Memory Management with Fifo\n\n### 相关页面\n\n相关主题：[System Architecture](#page-5), [Bilibili Surfer Example](#page-9)\n\n<details>\n<summary>Related Source Files</summary>\n\n以下源码文件用于生成本页说明：\n\n- [examples/bilibili_surfer/fifo.py](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.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# Memory Management with Fifo\n\n## Overview\n\nThe `Fifo` class implements a First-In-First-Out (FIFO) memory buffer for the CyclicAgent framework. It serves as a persistent memory mechanism that tracks agent actions over time, enabling stateful behavior across multiple execution cycles. The memory stores action records with timestamps and provides a formatted prompt interface for LLM consumption.\n\n**Purpose and Scope:**\n- Maintains a rolling history of agent actions with temporal ordering\n- Persists memory entries to a log file for debugging and auditability\n- Provides context to language models about past agent behavior\n- Enforces a configurable capacity limit to prevent unbounded memory growth\n\n资料来源：[examples/bilibili_surfer/fifo.py:1-35](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n\n## Architecture\n\nThe `Fifo` class is a simple yet effective memory component that integrates with the broader `BilibiliStateBase` abstraction. It operates as a bounded queue with automatic eviction of oldest entries.\n\n```mermaid\ngraph TD\n    A[Agent Action] -->|add| B[Fifo Memory]\n    B --> C{Capacity Check}\n    C -->|queue full| D[Evict Oldest Entry]\n    C -->|space available| E[Append to Queue]\n    D --> E\n    E --> F[Log to fifo_log.txt]\n    F --> G[Timestamp Added]\n    G --> H[Memory Buffer]\n    H --> I[LLM Context via prompt]\n    \n    style A fill:#e1f5fe\n    style I fill:#fff3e0\n```\n\nThe memory flows into agent decision-making through the `_infer_state_helper` method, which includes past actions in LLM prompts.\n\n资料来源：[examples/bilibili_surfer/fifo.py:1-35](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:38-52](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n\n## Class Reference\n\n### Fifo\n\nThe core memory management class.\n\n| Attribute | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `capacity` | `int` | `100` | Maximum number of entries before oldest eviction |\n| `queue` | `list` | `[]` | Internal storage for memory entries |\n| `log_file` | `str` | `\"fifo_log.txt\"` | Path to persistent log file |\n\n#### Methods\n\n##### `__init__()`\n\nInitializes the Fifo instance and ensures the log file exists.\n\n```python\ndef __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资料来源：[examples/bilibili_surfer/fifo.py:6-14](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n\n##### `add(item: str) -> None`\n\nAdds a string item to the memory buffer.\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `item` | `str` | The action/event string to record |\n\n**Behavior:**\n1. Validates that `item` is a string (raises `ValueError` otherwise)\n2. If capacity is reached, removes the oldest entry from index 0\n3. Attaches a timestamp in `YYYY-MM-DD HH:MM:SS` format\n4. Appends the tuple `(item, timestamp)` to the queue\n5. Logs the entry to the file system\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)  # Remove the oldest item to maintain capacity\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\n资料来源：[examples/bilibili_surfer/fifo.py:16-23](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n\n##### `prompt() -> str`\n\nGenerates a formatted string of all memory entries for LLM consumption.\n\n**Returns:** A newline-separated string with entries in reverse chronological order (most recent first), formatted as `{time} - {text}`.\n\n```python\ndef prompt(self):\n    return \"\\n\".join([f\"{time} - {text}\" for text, time in reversed(self.queue)])\n```\n\n资料来源：[examples/bilibili_surfer/fifo.py:30-31](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n\n##### `log_to_file(item: str, timestamp: str) -> None`\n\nAppends a timestamped entry to the persistent log file.\n\n```python\ndef log_to_file(self, item, timestamp):\n    with open(self.log_file, 'a') as file:\n        file.write(f\"{timestamp} - {item}\\n\")\n```\n\n资料来源：[examples/bilibili_surfer/fifo.py:25-28](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/fifo.py)\n\n## Integration with State Machine\n\nThe `Fifo` memory is integrated into the agent architecture through the `BilibiliStateBase` abstract base class, which composes the memory buffer with other required components.\n\n```mermaid\ngraph LR\n    A[BilibiliStateBase] --> B[Fifo Memory]\n    A --> C[Cohere Client]\n    A --> D[Bilibili Credential]\n    A --> E[Initial Prompt]\n    \n    F[_infer_state_helper] --> B\n    G[BrowsingVideo] --> A\n    H[ReadingComments] --> A\n    I[PostComment] --> A\n```\n\n**Base Class Composition:**\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:29-35](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n\n## Usage Patterns\n\n### Adding Memory Entries\n\nAgents record actions by calling `memory.add()` with descriptive strings:\n\n```python\n# Track search operations\nself.memory.add(f\"searched for {response} while browsing video\")\n\n# Record comment discovery\nself.memory.add(f\"finds comment: {cmt['content']['message']} while browsing {self.video_title}\")\n\n# Log posting activity\nself.memory.add(f\"commented {response} to {self.video_title}\")\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:88](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:108](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n\n### Including Memory in LLM Prompts\n\nThe `_infer_state_helper` method constructs prompts that include memory context:\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```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:38-49](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n\n### Initialization\n\nFifo is instantiated empty and passed to the initial state:\n\n```python\ninitial_state = BrowsingVideo(memory=Fifo(),\n                              initial_prompt=initial_prompt,\n                              co=Client(os.environ.get(\"COHERE_API_KEY\")),\n                              credential=Credential(...))\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:135-142](https://github.com/xingjianll/cyclic-agent/blob/main/examples/bilibili_surfer/bilibili_surfer.py)\n\n## Behavior Specifications\n\n| Aspect | Specification |\n|--------|---------------|\n| **Eviction Policy** | Oldest entry removed when capacity (100) is exceeded |\n| **Ordering** | Queue maintains insertion order; prompt reverses for recency-first display |\n| **Persistence** | All additions logged to `fifo_log.txt` in append mode |\n| **Type Constraint** | Only string values accepted; raises `ValueError` for non-strings |\n| **Timestamp Format** | ISO-style: `YYYY-MM-DD HH:MM:SS` |\n\n## Limitations and Considerations\n\n1. **Fixed Capacity**: The 100-item limit is hardcoded and cannot be configured per-instance without modifying source code.\n2. **File I/O on Every Add**: Each memory addition triggers a synchronous file write, which may impact performance in high-frequency scenarios.\n3. **No Query Filtering**: The `prompt()` method returns all entries; there is no mechanism to retrieve a subset by time range or pattern.\n4. **Shared Log File**: All instances write to `fifo_log.txt` by default; concurrent access from multiple processes may cause race conditions.\n\n---\n\n<a id='page-8'></a>\n\n## Hello World Example\n\n### 相关页面\n\n相关主题：[Installation and Setup](#page-1), [Creating Custom States](#page-6), [Bilibili Surfer Example](#page-9)\n\n<details>\n<summary>Relevant Source Files</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</details>\n\n# Hello World Example\n\n## Overview\n\nThe Hello World Example (`examples/hello_world/hello_world.py`) is the simplest demonstration of the CyclicAgent framework. It showcases the core state machine pattern by creating two mutually transitioning states that simulate a continuous question-answer loop using a Cohere LLM. 资料来源：[examples/hello_world/hello_world.py:1-31]()\n\n## Architecture\n\nCyclicAgent abstracts an agent as a **Finite State Machine (FSM)** using the State design pattern. Each state implements a `next()` method that returns another state, enabling indefinite chaining of transitions. 资料来源：[README.md](https://github.com/xingjianll/cyclic-agent#how-does-cyclicagent-work)\n\n### State Machine Diagram\n\n```mermaid\ngraph TD\n    A((Start)) --> B[AskQuestion State]\n    B -->|next()| C[AnswerQuestion State]\n    C -->|next()| B\n    B -->|5 iterations| D((End))\n    C -->|5 iterations| D\n```\n\n## Core Components\n\n### State Base Class\n\nThe `State` class is the foundation of the framework, defined as a generic Pydantic model:\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:5-9]()\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `SigT` | Generic TypeVar | Signal type for state communication |\n| `next()` | Abstract Method | Returns the next state in the FSM |\n\n### CyclicExecutor\n\nThe executor manages the state machine lifecycle:\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-8]()\n\n| Method | Description |\n|--------|-------------|\n| `start(initial_state)` | Begins executing the FSM in a separate thread |\n| `pause()` | Pauses execution (thread-safe) |\n| `resume()` | Resumes execution (thread-safe) |\n| `kill()` | Stops execution and joins the thread |\n\n## Example Implementation\n\n### AskQuestion State\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资料来源：[examples/hello_world/hello_world.py:13-18]()\n\n| Field | Type | Description |\n|-------|------|-------------|\n| Signal Type | `None` | This state does not accept external signals |\n| Return Type | `AnswerQuestion` | Transitions to the answer state with the question |\n\n### AnswerQuestion State\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资料来源：[examples/hello_world/hello_world.py:20-25]()\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `question` | `str` | Stored question from previous state |\n| Signal Type | `None` | Does not accept external signals |\n| Return Type | `AskQuestion` | Transitions back to ask a new question |\n\n## Execution Flow\n\n```mermaid\nsequenceDiagram\n    participant Main\n    participant Executor\n    participant AskQuestion\n    participant AnswerQuestion\n    participant CohereAPI\n\n    Main->>Executor: start(AskQuestion())\n    Executor->>AskQuestion: next()\n    AskQuestion->>CohereAPI: chat(\"Ask a question\")\n    CohereAPI-->>AskQuestion: question_text\n    AskQuestion->>AnswerQuestion: next(question=...)\n    \n    loop 5 times\n        Executor->>AnswerQuestion: next()\n        AnswerQuestion->>CohereAPI: chat(question)\n        CohereAPI-->>AnswerQuestion: answer\n        AnswerQuestion->>AskQuestion: next()\n        Executor->>AskQuestion: next()\n        AskQuestion->>CohereAPI: chat(\"Ask a question\")\n        CohereAPI-->>AskQuestion: new_question\n        AskQuestion->>AnswerQuestion: next(question=...)\n    end\n```\n\n## Configuration\n\n### Environment Setup\n\nThe example requires a `.env` file with the Cohere API key:\n\n```bash\nCOHERE_API_KEY=your_api_key_here\n```\n\n### Executor Configuration\n\n```python\nexecutor = CyclicExecutor(5)  # 5-second interval between state transitions\n```\n\n资料来源：[examples/hello_world/hello_world.py:28-29]()\n\n| Parameter | Value | Description |\n|-----------|-------|-------------|\n| `default_time_interval` | `5` (seconds) | Pause between each `next()` call |\n| `time.sleep(20)` | `20` (seconds) | Total runtime before natural exit |\n\n## Key Takeaways\n\n1. **State Pattern**: Each state is a Pydantic model that implements `next()`, returning the subsequent state 资料来源：[cyclic_agent/state.py:5-9]()\n\n2. **Thread Safety**: The executor uses `threading.Lock` for safe pause/resume/kill operations 资料来源：[cyclic_agent/executor.py:4]()\n\n3. **Type Safety**: Generic type parameters (`State[SigT]`) ensure compile-time safety for signal types 资料来源：[cyclic_agent/state.py:5]()\n\n4. **Extensibility**: New states can be added by inheriting from `State` and implementing the `next()` method\n\n## Running the Example\n\n```bash\n# Install dependencies\npip install cyclic-agent cohere python-dotenv\n\n# Set up environment\nexport COHERE_API_KEY=your_key\n\n# Run\npython examples/hello_world/hello_world.py\n```\n\nThe example will print alternating questions and answers for approximately 20 seconds before exiting.\n\n---\n\n<a id='page-9'></a>\n\n## Bilibili Surfer Example\n\n### 相关页面\n\n相关主题：[Creating Custom States](#page-6), [Memory Management with Fifo](#page-7), [Hello World Example](#page-8)\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 Example\n\nThe Bilibili Surfer is a demonstration application built on the CyclicAgent framework that creates an autonomous AI agent capable of browsing Bilibili, a Chinese video-sharing platform. The agent autonomously searches for videos, reads comments, and interacts by posting replies, simulating a realistic user experience with automatic disclosure as a bot.\n\n## Architecture Overview\n\nThe Bilibili Surfer exemplifies the CyclicAgent's finite state machine (FSM) design pattern. The agent operates as a cyclical state machine where each state implements a `next()` method that returns the subsequent state, enabling indefinite chaining of state transitions.\n\n```mermaid\ngraph TD\n    A([BrowsingVideo]) -->|select video| B([ReadingComments])\n    A -->|search again| A\n    B -->|select comment| C([PostComment])\n    B -->|back to browse| A\n    C -->|complete| A\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:1-150]()\n\n## State Components\n\n### BilibiliStateBase (Abstract Base)\n\nAll Bilibili states inherit from `BilibiliStateBase`, which combines the `State` abstract class with common attributes required across all states.\n\n| Attribute | Type | Description |\n|-----------|------|-------------|\n| `memory` | `Fifo` | Queue storing past agent actions with timestamps |\n| `co` | `Client` | Cohere API client for LLM interactions |\n| `credential` | `Credential` | Bilibili API authentication credentials |\n| `initial_prompt` | `str` | System prompt defining agent persona |\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:35-43]()\n\nThe base class provides the `_infer_state_helper()` method that constructs prompts for LLM-based state inference:\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```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:45-58]()\n\n### BrowsingVideo State\n\nThe entry point state where the agent searches for and selects videos to watch.\n\n**Type Definition:**\n```python\ntype BrowsingVideoReachable = Union[BrowsingVideo, ReadingComments]\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:61-62]()\n\n**Workflow:**\n\n1. Generate a search keyword phrase via LLM (max 3 Chinese words)\n2. Execute Bilibili video search ordered by fan count\n3. Present top 10 results to LLM for selection\n4. Log selection to memory\n5. Transition to `ReadingComments` or remain in `BrowsingVideo`\n\n```python\ndef next(self, signal: None = None) -> BrowsingVideoReachable:\n    print('BrowsingVideo')\n    prompt = I(\n        f\"\"\"\n        {self.initial_prompt}\n        Here are your past actions {self.memory.prompt()} Generate a keyword phrase for videos you want to watch.\n        Be creative and avoid repeating. Respond with a maximum of three words in Chinese.\n        \"\"\"\n    )\n    response = self.co.chat(temperature=1, message=prompt).text\n    res = asyncio.run(search.search_by_type(response,\n                                            search_type=search.SearchObjectType.VIDEO,\n                                            order_type=search.OrderUser.FANS,\n                                            order_sort=0\n                                            )\n                      )\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:64-79]()\n\n### ReadingComments State\n\nEnables the agent to examine and select comments from a specific video for potential interaction.\n\n**Type Definition:**\n```python\ntype ReadingCommentsReachable = Union[BrowsingVideo, ReadingComments, PostComment]\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:118-119]()\n\n**Required Attributes:**\n\n| Attribute | Type | Description |\n|-----------|------|-------------|\n| `video_bvid` | `str` | Bilibili video BV identifier |\n| `video_title` | `str` | Video title for context |\n| `video_description` | `str` | Video description for context |\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:121-126]()\n\n**Workflow:**\n\n1. Fetch top comments ordered by likes via Bilibili API\n2. Present comments to LLM for selection\n3. Based on LLM decision, either:\n   - Return to `BrowsingVideo`\n   - Stay in `ReadingComments`\n   - Transition to `PostComment` with reply context\n\n```python\nmatch self._infer_state_helper('BrowsingVideo', 'ReadingComments', 'PostComment'):\n    case 'BrowsingVideo':\n        return BrowsingVideo(**self.model_dump(exclude={'video_bvid', 'video_title', 'video_description'}))\n    case 'ReadingComments':\n        return self\n    case 'PostComment':\n        return PostComment(**self.model_dump(), reply_to=cmt['content']['message'], reply_to_oid=cmt['oid'])\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:141-148]()\n\n### PostComment State\n\nHandles automatic reply generation and posting to Bilibili.\n\n**Type Definition:**\n```python\ntype PostCommentReachable = Union[BrowsingVideo]\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:93-94]()\n\n**Attributes:**\n\n| Attribute | Type | Description |\n|-----------|------|-------------|\n| `reply_to` | `str \\| None` | Original comment content being replied to |\n| `reply_to_oid` | `int \\| None` | Original comment OID for threading |\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:96-99]()\n\n**Workflow:**\n\n1. Generate reply content via LLM based on:\n   - Original comment being replied to\n   - Video context (title, description)\n2. Append automatic disclosure footnote\n3. Post comment to video via Bilibili API\n4. Create and publish a Bilibili \"Dynamic\" (post) with:\n   - Video link\n   - Reply content\n   - Disclosure notice\n5. Return to `BrowsingVideo` state\n\n```python\nresponse = self.co.chat(temperature=1, message=prompt).text\nfootnote = (\n    f\"\\n I am a bot, and this action was performed automatically. Please contact {os.getenv('name')}\"\n    f\" if you have any questions or concerns.\"\n)\nasyncio.run(comment.send_comment(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资料来源：[examples/bilibili_surfer/bilibili_surfer.py:106-117]()\n\n## Memory System: Fifo\n\nThe `Fifo` class implements a bounded queue for storing agent action history, providing the agent with contextual awareness of past behaviors.\n\n资料来源：[examples/bilibili_surfer/fifo.py:1-25]()\n\n### Configuration\n\n| Parameter | Default | Description |\n|-----------|---------|-------------|\n| `capacity` | 100 | Maximum stored actions before oldest are evicted |\n| `log_file` | `\"fifo_log.txt\"` | Persistent log file for action history |\n\n### Core Methods\n\n| Method | Description |\n|--------|-------------|\n| `add(item: str)` | Appends action with timestamp, evicts oldest if at capacity |\n| `prompt()` | Returns formatted history string (newest first) |\n\n```python\ndef prompt(self):\n    return \"\\n\".join([f\"{time} - {text}\" for text, time in reversed(self.queue)])\n```\n\n资料来源：[examples/bilibili_surfer/fifo.py:24-25]()\n\n## Execution Model\n\nThe `CyclicExecutor` manages the state machine lifecycle in a dedicated thread.\n\n资料来源：[cyclic_agent/executor.py:1-47]()\n\n### Executor Configuration\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `default_time_interval` | `float` | Seconds between state transitions |\n| `running` | `bool` | Execution status flag |\n| `killed` | `bool` | Permanent stop signal |\n\n### Control Methods\n\n| Method | Description |\n|--------|-------------|\n| `start(initial_state)` | Launch executor thread with initial state |\n| `pause()` | Suspend state transitions |\n| `resume()` | Continue suspended execution |\n| `kill()` | Stop execution and join thread |\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:36-44]()\n\n## Data Flow Diagram\n\n```mermaid\nsequenceDiagram\n    participant User\n    participant Executor\n    participant LLM as Cohere LLM\n    participant Bilibili as Bilibili API\n    participant Memory as Fifo Memory\n\n    Executor->>BrowsingVideo: start(initial_state)\n    BrowsingVideo->>LLM: Generate search query\n    BrowsingVideo->>Bilibili: search.search_by_type()\n    Bilibili-->>BrowsingVideo: Top 10 videos\n    BrowsingVideo->>Memory: add(finds {title})\n    BrowsingVideo->>ReadingComments: next()\n\n    ReadingComments->>Bilibili: comment.get_comments()\n    Bilibili-->>ReadingComments: Top 5 comments\n    ReadingComments->>Memory: add(find comment)\n    ReadingComments->>PostComment: next(reply_to)\n\n    PostComment->>LLM: Generate reply\n    PostComment->>Memory: add(commented)\n    PostComment->>Bilibili: comment.send_comment()\n    PostComment->>Bilibili: dynamic.send_dynamic()\n    PostComment->>BrowsingVideo: next()\n```\n\n## Setup and Usage\n\n### Prerequisites\n\nRequired environment variables:\n\n| Variable | Description |\n|----------|-------------|\n| `COHERE_API_KEY` | Cohere API key for LLM access |\n| `SESSDATA` | Bilibili session data cookie |\n| `BILI_JCT` | Bilibili CSRF token |\n| `BUVID3` | Bilibili user identifier cookie |\n| `name` | Contact name for bot disclosure |\n\n### Running the Example\n\n```python\nif __name__ == \"__main__\":\n    initial_prompt = \"You are a dude browsing Bilibili, A Chinese video sharing platform.\"\n\n    initial_state = BrowsingVideo(memory=Fifo(),\n                                  initial_prompt=initial_prompt,\n                                  co=Client(os.environ.get(\"COHERE_API_KEY\")),\n                                  credential=Credential(sessdata=SESSDATA,\n                                                        bili_jct=BILI_JCT,\n                                                        buvid3=BUVID3\n                                                        )\n                                  )\n    executor = CyclicExecutor(5)  # 5-second intervals\n    executor.start(initial_state)\n    time.sleep(1000)  # Run for ~16 minutes\n```\n\n资料来源：[examples/bilibili_surfer/bilibili_surfer.py:163-180]()\n\n## State Transition Matrix\n\n| Current State | Action | Next State |\n|---------------|--------|------------|\n| `BrowsingVideo` | Select video | `ReadingComments` |\n| `BrowsingVideo` | Search again | `BrowsingVideo` |\n| `ReadingComments` | Choose comment | `PostComment` |\n| `ReadingComments` | Browse more | `BrowsingVideo` |\n| `ReadingComments` | Stay | `ReadingComments` |\n| `PostComment` | Complete | `BrowsingVideo` |\n\n## Integration with Core Framework\n\nThe Bilibili Surfer demonstrates CyclicAgent's extensibility:\n\n1. **State Pattern**: Each state extends `State[None]`, implementing the `next()` abstract method\n   - 资料来源：[cyclic_agent/state.py:1-15]()\n\n2. **Type Annotations**: Python 3.12+ type unions define reachable states for type safety\n   - 资料来源：[cyclic_agent/__init__.py:1-6]()\n\n3. **Pydantic Models**: States use `BaseModel` for automatic serialization and validation\n   - 资料来源：[cyclic_agent/state.py:5]()\n\n4. **Dependency Injection**: States receive dependencies via constructor, enabling testability\n\n---\n\n<a id='page-10'></a>\n\n## Helper States\n\n### 相关页面\n\n相关主题：[State Base Class](#page-3), [Creating Custom States](#page-6)\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/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/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# Helper States\n\n## Overview\n\nHelper States are reusable, composable state components in CyclicAgent that encapsulate common patterns for LLM-powered agent workflows. They serve as building blocks that developers can extend, combine, or integrate into custom state machines to accelerate agent development.\n\nUnlike application-specific states (e.g., `AskQuestion` or `BrowsingVideo`), helper states focus on generic operational patterns such as search, chain-of-thought reasoning, and callback-driven transitions. They follow the same finite state machine (FSM) architecture as all states in CyclicAgent, ensuring seamless integration with the `CyclicExecutor`.\n\n资料来源：[cyclic_agent/__init__.py:1-6]()\n\n## Architecture\n\nHelper states inherit from the base `State` class and implement the `next()` method to define transitions. They typically leverage callbacks for flexible exit behavior, allowing parent states to control the flow after the helper completes its operation.\n\n```mermaid\ngraph TD\n    A[Parent State] -->|creates| B[Helper State]\n    B -->|executes operation| C[Result/Action]\n    C -->|callback| D[Exit Callback]\n    D -->|returns| A[Parent State or Next State]\n```\n\n### Base State Contract\n\nAll states, including helpers, must implement:\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-9]()\n\n## Chain of Thought (CoT) Helper\n\n### Purpose\n\nThe `CoT` class provides a reusable wrapper for chain-of-thought reasoning patterns. It automatically appends \"Let's think step by step.\" to prompts, enabling step-by-step reasoning in LLM responses.\n\n资料来源：[cyclic_agent/cot.py:1-5]()\n\n### Class Definition\n\n```python\nclass CoT(State[None]):\n    exit_: Callable[[str], State]\n    llm: State\n    prompt: str\n```\n\n### Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `exit_` | `Callable[[str], State]` | Callback invoked with the LLM's response; returns the next state |\n| `llm` | `State` | The LLM state used to generate responses |\n| `prompt` | `str` | The base prompt to which chain-of-thought suffix is added |\n\n### Implementation\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\n资料来源：[cyclic_agent/cot.py:7-14]()\n\n### Usage Pattern\n\nThe `CoT` helper demonstrates a callback-driven transition pattern where:\n\n1. The helper augments the prompt with reasoning instructions\n2. The LLM processes the enhanced prompt\n3. The result is passed to the exit callback\n4. Control returns to the calling state or transitions to a new state\n\n```mermaid\nsequenceDiagram\n    participant P as Parent State\n    participant C as CoT Helper\n    participant L as LLM State\n    participant E as Exit Callback\n    \n    P->>C: Creates CoT with prompt, llm, exit_\n    C->>C: Appends \"Let's think step by step.\"\n    C->>L: Calls llm with enhanced prompt\n    L-->>C: Returns reasoning answer\n    C->>E: Invokes callback with answer\n    E-->>P: Returns next State\n```\n\n## Search Helper\n\n### Purpose\n\nThe `Search` class provides a generic search operation pattern. It accepts a query, executes a search (to be implemented by subclass), and passes results to an exit callback for further processing.\n\n资料来源：[cyclic_agent/search.py:1-5]()\n\n### Class Definition\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### Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `query` | `str` | The search query string |\n| `exit_` | `Callable[[list[str]], State]` | Callback receiving search results; returns the next state |\n\n### Key Design Patterns\n\n1. **Abstract Search Method**: The `search()` method raises `NotImplementedError`, requiring subclasses to provide concrete implementations.\n2. **Typed Callback**: The exit callback uses `Annotated` to document that it receives search results as a list of strings.\n3. **Separation of Concerns**: Search logic is decoupled from state transition logic.\n\n资料来源：[cyclic_agent/search.py:6-12]()\n\n### Subclass Implementation Example\n\n```python\nclass VideoSearch(Search):\n    def search(self, query: str) -> str:\n        # Concrete implementation\n        results = video_api.search(query)\n        return formatted_results\n```\n\n## Callback-Driven Transition Pattern\n\nBoth helper states employ a consistent callback pattern for state transitions:\n\n```mermaid\ngraph LR\n    A[Helper State] --> B{Operation Complete}\n    B --> C[Exit Callback]\n    C --> D[Next State]\n    D --> E[CyclicExecutor]\n    E --> A\n```\n\n### Benefits\n\n| Benefit | Description |\n|---------|-------------|\n| **Decoupling** | Helper states don't need to know about subsequent states |\n| **Composability** | Same helper can be reused with different callbacks |\n| **Flexibility** | Callbacks can implement complex routing logic |\n| **Testability** | Callbacks can be easily mocked for unit testing |\n\n## Integration with CyclicExecutor\n\nHelper states integrate seamlessly with the executor:\n\n```python\nclass CyclicExecutor:\n    def _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:26-32]()\n\nThe executor continuously calls `next()` on any state, including helpers. Each helper's `next()` either:\n- Returns another state (transition)\n- Returns the same state (loop continuation)\n\n## Creating Custom Helper States\n\n### Template\n\n```python\nfrom cyclic_agent import State\n\nclass MyHelper(State[None]):\n    data: str\n    exit_: Callable[[ResultType], State]\n\n    def next(self, signal: None = None) -> State:\n        # Perform helper operation\n        result = self.perform_operation()\n        # Delegate to callback for next state\n        return self.exit_(result)\n\n    def perform_operation(self) -> ResultType:\n        raise NotImplementedError\n```\n\n### Checklist\n\n- [ ] Inherit from `State[None]`\n- [ ] Define exit callback as `Callable` parameter\n- [ ] Implement `next()` method returning `State`\n- [ ] Call exit callback with operation result\n- [ ] Raise `NotImplementedError` for subclass-specific methods\n\n## Comparison: CoT vs Search Helpers\n\n| Aspect | CoT | Search |\n|--------|-----|--------|\n| **Primary Function** | Reasoning wrapper | Search operation |\n| **Exit Callback Parameter** | `Callable[[str], State]` | `Callable[[list[str]], State]` |\n| **Abstract Methods** | None | `search(query: str)` |\n| **Prompt Modification** | Appends reasoning suffix | None |\n| **Use Case** | Step-by-step reasoning | Information retrieval |\n\n## Export Configuration\n\nHelper states are available via the cyclic_agent package:\n\n```python\nfrom cyclic_agent import State, CyclicExecutor\n\n__all__ = [\"State\", \"CyclicExecutor\"]\n```\n\nDirect imports for specific helpers:\n\n```python\nfrom cyclic_agent.cot import CoT\nfrom cyclic_agent.search import Search\n```\n\n资料来源：[cyclic_agent/__init__.py:1-6]()\n\n## Best Practices\n\n1. **Use Helpers as Building Blocks**: Compose helpers within custom states rather than subclassing them.\n2. **Type Your Callbacks**: Always specify callback signatures for type safety.\n3. **Handle Edge Cases**: Implement error handling in `next()` for production use.\n4. **Document State Transitions**: Use type aliases (e.g., `ReachableStates`) to document possible transitions.\n5. **Maintain State Immutability**: Helper states should not mutate shared state; use callbacks for side effects.\n\n---\n\n---\n\n## Doramagic Pitfall Log\n\nProject: xingjianll/cyclic-agent\n\nSummary: Found 6 potential pitfall items; 0 are high/blocking. Highest priority: capability - 能力判断依赖假设.\n\n## 1. capability · 能力判断依赖假设\n\n- Severity: medium\n- Evidence strength: source_linked\n- Finding: README/documentation is current enough for a first validation pass.\n- User impact: 假设不成立时，用户拿不到承诺的能力。\n- Suggested check: 将假设转成下游验证清单。\n- Guardrail action: 假设必须转成验证项；没有验证结果前不能写成事实。\n- Evidence: capability.assumptions | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | README/documentation is current enough for a first validation pass.\n\n## 2. maintenance · 维护活跃度未知\n\n- Severity: medium\n- Evidence strength: source_linked\n- Finding: 未记录 last_activity_observed。\n- User impact: 新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。\n- Suggested check: 补 GitHub 最近 commit、release、issue/PR 响应信号。\n- Guardrail action: 维护活跃度未知时，推荐强度不能标为高信任。\n- Evidence: evidence.maintainer_signals | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | last_activity_observed missing\n\n## 3. security_permissions · 下游验证发现风险项\n\n- Severity: medium\n- Evidence strength: source_linked\n- Finding: no_demo\n- User impact: 下游已经要求复核，不能在页面中弱化。\n- Suggested check: 进入安全/权限治理复核队列。\n- Guardrail action: 下游风险存在时必须保持 review/recommendation 降级。\n- Evidence: downstream_validation.risk_items | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | no_demo; severity=medium\n\n## 4. security_permissions · 存在评分风险\n\n- Severity: medium\n- Evidence strength: source_linked\n- Finding: no_demo\n- User impact: 风险会影响是否适合普通用户安装。\n- Suggested check: 把风险写入边界卡，并确认是否需要人工复核。\n- Guardrail action: 评分风险必须进入边界卡，不能只作为内部分数。\n- Evidence: risks.scoring_risks | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | no_demo; severity=medium\n\n## 5. maintenance · issue/PR 响应质量未知\n\n- Severity: low\n- Evidence strength: source_linked\n- Finding: issue_or_pr_quality=unknown。\n- User impact: 用户无法判断遇到问题后是否有人维护。\n- Suggested check: 抽样最近 issue/PR，判断是否长期无人处理。\n- Guardrail action: issue/PR 响应未知时，必须提示维护风险。\n- Evidence: evidence.maintainer_signals | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | issue_or_pr_quality=unknown\n\n## 6. maintenance · 发布节奏不明确\n\n- Severity: low\n- Evidence strength: source_linked\n- Finding: release_recency=unknown。\n- User impact: 安装命令和文档可能落后于代码，用户踩坑概率升高。\n- Suggested check: 确认最近 release/tag 和 README 安装命令是否一致。\n- Guardrail action: 发布节奏未知或过期时，安装说明必须标注可能漂移。\n- Evidence: 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 output with a Doramagic pitfall appendix.",
      "title": "Human Manual"
    },
    "pitfall_log": {
      "asset_id": "pitfall_log",
      "filename": "PITFALL_LOG.md",
      "markdown": "# Pitfall Log\n\nProject: xingjianll/cyclic-agent\n\nSummary: Found 6 potential pitfall items; 0 are high/blocking. Highest priority: capability - 能力判断依赖假设.\n\n## 1. capability · 能力判断依赖假设\n\n- Severity: medium\n- Evidence strength: source_linked\n- Finding: README/documentation is current enough for a first validation pass.\n- User impact: 假设不成立时，用户拿不到承诺的能力。\n- Suggested check: 将假设转成下游验证清单。\n- Guardrail action: 假设必须转成验证项；没有验证结果前不能写成事实。\n- Evidence: capability.assumptions | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | README/documentation is current enough for a first validation pass.\n\n## 2. maintenance · 维护活跃度未知\n\n- Severity: medium\n- Evidence strength: source_linked\n- Finding: 未记录 last_activity_observed。\n- User impact: 新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。\n- Suggested check: 补 GitHub 最近 commit、release、issue/PR 响应信号。\n- Guardrail action: 维护活跃度未知时，推荐强度不能标为高信任。\n- Evidence: evidence.maintainer_signals | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | last_activity_observed missing\n\n## 3. security_permissions · 下游验证发现风险项\n\n- Severity: medium\n- Evidence strength: source_linked\n- Finding: no_demo\n- User impact: 下游已经要求复核，不能在页面中弱化。\n- Suggested check: 进入安全/权限治理复核队列。\n- Guardrail action: 下游风险存在时必须保持 review/recommendation 降级。\n- Evidence: downstream_validation.risk_items | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | no_demo; severity=medium\n\n## 4. security_permissions · 存在评分风险\n\n- Severity: medium\n- Evidence strength: source_linked\n- Finding: no_demo\n- User impact: 风险会影响是否适合普通用户安装。\n- Suggested check: 把风险写入边界卡，并确认是否需要人工复核。\n- Guardrail action: 评分风险必须进入边界卡，不能只作为内部分数。\n- Evidence: risks.scoring_risks | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | no_demo; severity=medium\n\n## 5. maintenance · issue/PR 响应质量未知\n\n- Severity: low\n- Evidence strength: source_linked\n- Finding: issue_or_pr_quality=unknown。\n- User impact: 用户无法判断遇到问题后是否有人维护。\n- Suggested check: 抽样最近 issue/PR，判断是否长期无人处理。\n- Guardrail action: issue/PR 响应未知时，必须提示维护风险。\n- Evidence: evidence.maintainer_signals | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | issue_or_pr_quality=unknown\n\n## 6. maintenance · 发布节奏不明确\n\n- Severity: low\n- Evidence strength: source_linked\n- Finding: release_recency=unknown。\n- User impact: 安装命令和文档可能落后于代码，用户踩坑概率升高。\n- Suggested check: 确认最近 release/tag 和 README 安装命令是否一致。\n- Guardrail action: 发布节奏未知或过期时，安装说明必须标注可能漂移。\n- Evidence: evidence.maintainer_signals | art_2a2d1b4b3cfd487880b7144fa08bc9e2 | https://github.com/xingjianll/cyclic-agent#readme | release_recency=unknown\n",
      "summary": "Identity, installation, configuration, runtime, and safety pitfalls before user trial.",
      "title": "Pitfall Log"
    },
    "prompt_preview": {
      "asset_id": "prompt_preview",
      "filename": "PROMPT_PREVIEW.md",
      "markdown": "# cyclic-agent - Prompt Preview\n\n> Copy the prompt below into your AI host before installing anything.\n> Its purpose is to let you safely feel the project's workflow, not to claim the project has already run.\n\n## Copy this prompt\n\n```text\nYou are using an independent Doramagic capability pack for xingjianll/cyclic-agent.\n\nProject:\n- Name: cyclic-agent\n- Repository: https://github.com/xingjianll/cyclic-agent\n- Summary: <div align= \"center\">\n- Host target: local_cli\n\nGoal:\nHelp me evaluate this project for the following task without installing it yet: <div align= \"center\">\n\nBefore taking action:\n1. Restate my task, success standard, and boundary.\n2. Identify whether the next step requires tools, browser access, network access, filesystem access, credentials, package installation, or host configuration.\n3. Use only the Doramagic Project Pack, the upstream repository, and the source-linked evidence listed below.\n4. If a real command, install step, API call, file write, or host integration is required, mark it as \"requires post-install verification\" and ask for approval first.\n5. If evidence is missing, say \"evidence is missing\" instead of filling the gap.\n\nPreviewable capabilities:\n- Capability 1: <div align= \"center\">\n\nCapabilities that require post-install verification:\n- Capability 1: Use the source-backed project context to guide one small, checkable workflow step.\n\nCore service flow:\n1. page-1: Installation and Setup. Produce one small intermediate artifact and wait for confirmation.\n2. page-2: Project Overview. Produce one small intermediate artifact and wait for confirmation.\n3. page-3: State Base Class. Produce one small intermediate artifact and wait for confirmation.\n4. page-4: CyclicExecutor. Produce one small intermediate artifact and wait for confirmation.\n5. page-5: System Architecture. Produce one small intermediate artifact and wait for confirmation.\n\nSource-backed evidence to keep in mind:\n- https://github.com/xingjianll/cyclic-agent#readme\n- pyproject.toml\n- README.md\n- cyclic_agent/state.py\n- cyclic_agent/__init__.py\n- cyclic_agent/executor.py\n- examples/bilibili_surfer/bilibili_surfer.py\n\nFirst response rules:\n1. Start Step 1 only.\n2. Explain the one service action you will perform first.\n3. Ask exactly three questions about my target workflow, success standard, and sandbox boundary.\n4. Stop and wait for my answers.\n\nStep 1 follow-up protocol:\n- After I answer the first three questions, stay in Step 1.\n- Produce six parts only: clarified task, success standard, boundary conditions, two or three options, tradeoffs for each option, and one recommendation.\n- End by asking whether I confirm the recommendation.\n- Do not move to Step 2 until I explicitly confirm.\n\nConversation rules:\n- Advance one step at a time and wait for confirmation after each small artifact.\n- Write outputs as recommendations or planned checks, not as completed execution.\n- Do not claim tests passed, files changed, commands ran, APIs were called, or the project was installed.\n- If the user asks for execution, first provide the sandbox setup, expected output, rollback, and approval checkpoint.\n```\n",
      "summary": "不安装项目也能感受能力节奏的安全试用 Prompt。",
      "title": "Prompt Preview / 安装前试用 Prompt"
    },
    "quick_start": {
      "asset_id": "quick_start",
      "filename": "QUICK_START.md",
      "markdown": "# Quick Start\n\nProject: xingjianll/cyclic-agent\n\n## Official Entry Points\n\n### Python / pip · 官方安装入口\n\n```bash\npip install cyclic-agent\n```\n\nSource：https://github.com/xingjianll/cyclic-agent#readme\n\n## Sources\n\n- docs: https://github.com/xingjianll/cyclic-agent#readme\n",
      "summary": "Entry points extracted from official README or installation documentation.",
      "title": "Quick Start"
    }
  },
  "validation_id": "dval_5d1a5684881840c7a9f8cecb96cb914a"
}
