Skip to content

CharmNight/charmflow-agent-runtime

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

CharmFlow Agent Runtime

License Java Status Spring Boot

Status: Alpha。当前仍处于 0.x 阶段,公开 API 与 SPI 已经划出边界,但仍在继续收敛。首次正式发布前,不提供旧 alpha 快照的兼容层、弃用桥接或 schema 兼容桥接;生产接入前请锁定精确版本并自行完成升级验证。

Publishing: 当前仓库尚未发布到任何 Maven 仓库,包括 Maven Central、GitHub Packages 或其他私有 Maven 仓库。现在请先在仓库根目录执行 ./mvnw clean install,再从本地 Maven 缓存引用这些模块;仓库中的 Maven release profile 仅作为未来正式发布时的预留配置。

CharmFlow Agent Runtime 是一个嵌入 Spring Boot 应用的多步骤 Agent 执行框架。它把任务建模为显式的 step DAG,由本地 AgentEngine 驱动执行、恢复、查询、导出和观测,而不是把业务流程退化成单轮聊天。

当前能力

  • TaskResult 已切换到稳定读取面:finalResultstepResultsbusinessArtifactssystemArtifactsexports
  • 内置 Markdown / HTML / JSON / PDF exporter 默认不再把 systemArtifacts 写进交付文件。
  • @AgentTask.resultType / resultProjectorexecute(..., Class<T>)getResult(..., Class<T>) 组成真正可用的 typed final result。
  • 调度器既支持静态 fan-out / fan-in,也支持通过 @AgentFanOut / @AgentFanIn 显式声明的单层运行时动态展开与汇聚。
  • 控制面支持 pauseresumecancel、任务列表分页、step run 分页。
  • 事件体系支持 task / step 生命周期事件、监听器扩展、事件持久化。
  • starter 提供基础 metrics、observation、Actuator endpoint 集成。
  • JPA 存储使用 Flyway migration 管理 schema,不再依赖运行时 auto-DDL。
  • 当前运行边界仍是单进程:结果、step run、artifact、event 可以持久化,但不保证进程重启后自动恢复在途异步任务或未完成的 pause / resume / cancel 控制流程。
  • 仓库内包含 benchmark 资产、性能容量建议、API 稳定性边界和 semver / deprecation 说明。
  • 开源版支持边界、安全基线、自定义存储 SPI 示例和依赖扫描流程均已单独留档,便于发布前审阅。

模块

  • charmflow-agent-core 注解、模型、执行引擎、artifact schema/codec、导出器、事件与核心 SPI;不再承载 Spring Boot 包扫描假设。
  • charmflow-agent-spring-boot-starter Spring Boot 自动装配、@AgentTask 类路径扫描、默认 AgentEngine、事件发布器、metrics / observation / Actuator 接线。
  • charmflow-agent-storage-memory 默认内存存储实现,适合本地开发和测试。
  • charmflow-agent-storage-jpa JPA 持久化实现,当前仓库内提供 H2 与 MySQL 的 Flyway migration,并通过 JpaStorageDialect SPI 按数据库 vendor 选择脚本。模块本身不绑定具体 JDBC 驱动,数据库驱动与 Flyway 的数据库扩展由使用方主项目按需引入。
  • charmflow-agent-benchmarks 基于 JMH 的 benchmark 模块,用于比较顺序 baseline 与静态并行 DAG。

快速开始

1. 本地安装

./mvnw clean install

2. 添加依赖

最小组合是 starter 加一个存储实现。

<dependency>
    <groupId>com.charmflow.agent</groupId>
    <artifactId>charmflow-agent-spring-boot-starter</artifactId>
    <version>0.1.0</version>
</dependency>

<dependency>
    <groupId>com.charmflow.agent</groupId>
    <artifactId>charmflow-agent-storage-memory</artifactId>
    <version>0.1.0</version>
</dependency>

如果需要持久化存储,改为:

<dependency>
    <groupId>com.charmflow.agent</groupId>
    <artifactId>charmflow-agent-storage-jpa</artifactId>
    <version>0.1.0</version>
</dependency>

如果你的业务应用使用 MySQL,还需要在业务应用里额外引入数据库驱动和 Flyway 的 MySQL 扩展:

<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>

<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-mysql</artifactId>
    <scope>runtime</scope>
</dependency>

storage-jpa 的数据库接入边界:

  • 内置仅提供 h2mysql 两个 JpaStorageDialect
  • 方言解析顺序是:agent.storage.jpa.dialect 显式指定优先;否则根据 spring.flyway.url / spring.datasource.url 与驱动自动识别。
  • 如果既没有命中内置或第三方方言,也没有显式配置 spring.flyway.locations,应用会在启动期直接失败,而不是默默加载错误脚本。
  • 如果你要接 PostgreSQL、Oracle 等其他数据库,请在业务应用或独立扩展模块里同时提供 JDBC 驱动、对应 Flyway 数据库扩展,以及一个注册为 Spring Bean 的 JpaStorageDialect 实现。

更完整说明见 docs/jpa-storage-dialect-and-driver-boundary.md

3. 启用平台与配置

import com.charmflow.agent.annotation.EnableAgentPlatform;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@EnableAgentPlatform
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
agent:
  enabled: true
  storage:
    type: IN_MEMORY # IN_MEMORY | JPA
  export:
    base-dir: ./agent-output

选择 JPA 存储时,schema 由 Flyway migration 管理;默认示例使用 H2,切换到 MySQL 时需要额外引入数据库驱动和 Flyway MySQL 扩展(见上方依赖说明)。通常不需要手工设置 spring.jpa.database-platform,让 Hibernate 根据 JDBC 连接自动识别即可。

线程池、Actuator endpoint 和 exporter 的详细配置见 docs/execution-pool-configuration.md

4. 声明任务图

import com.charmflow.agent.annotation.AgentStep;
import com.charmflow.agent.annotation.AgentTask;
import com.charmflow.agent.model.ExportType;

@AgentTask(
        code = "release-guide-task",
        name = "Release Guide Task",
        exportTypes = {ExportType.MARKDOWN},
        inputType = ReleaseGuideInput.class,
        resultType = ReleaseGuide.class,
        resultProjector = ReleaseGuideProjector.class
)
public class ReleaseGuideTask {

    @AgentStep(code = "prepare", executor = PrepareExecutor.class, outputType = PreparedBrief.class)
    public void prepare() {
    }

    @AgentStep(code = "outline", dependsOn = {"prepare"}, executor = OutlineExecutor.class, outputType = OutlineSection.class)
    public void outline() {
    }

    @AgentStep(code = "checklist", dependsOn = {"prepare"}, executor = ChecklistExecutor.class, outputType = ChecklistSection.class)
    public void checklist() {
    }

    @AgentStep(code = "compose", dependsOn = {"outline", "checklist"}, executor = ComposeExecutor.class, outputType = String.class)
    public void compose() {
    }
}

上面的任务图就是一个固定 fan-out / fan-in:

          ┌─── outline ───┐
prepare ──┤               ├── compose
          └─── checklist ──┘

如果需要运行时动态展开,可以显式使用 @AgentFanOut / @AgentFanIn

import com.charmflow.agent.annotation.AgentFanIn;
import com.charmflow.agent.annotation.AgentFanOut;

@AgentTask(code = "batch-release-task", name = "Batch Release Task", inputType = BatchReleaseInput.class)
public class BatchReleaseTask {

    @AgentStep(code = "prepare", executor = PrepareBatchExecutor.class, outputType = java.util.List.class)
    public void prepare() {
    }

    @AgentFanOut(
            code = "write-item",
            dependsOn = {"prepare"},
            itemsFrom = "prepare",
            itemType = ReleaseSectionBrief.class,
            executor = WriteSectionExecutor.class,
            outputType = ReleaseSection.class
    )
    public void writeItem() {
    }

    @AgentFanIn(
            code = "compose",
            dependsOn = {"write-item"},
            gathers = "write-item",
            executor = ComposeBatchExecutor.class,
            outputType = String.class
    )
    public void compose() {
    }
}

5. 执行、查询与导出

import com.charmflow.agent.model.ExportType;
import com.charmflow.agent.model.PageRequest;
import com.charmflow.agent.model.TaskQuery;
import com.charmflow.agent.model.TaskResult;
import com.charmflow.agent.model.TaskSummary;
import com.charmflow.agent.spi.AgentEngine;

ReleaseGuide typed = agentEngine.execute("release-guide-task", input, ReleaseGuide.class);

TaskResult taskResult = agentEngine.execute("release-guide-task", input);
TaskResult sameTask = agentEngine.getResult(taskResult.taskId());
ReleaseGuide typedAgain = agentEngine.getResult(taskResult.taskId(), ReleaseGuide.class);

agentEngine.pause(taskResult.taskId());
agentEngine.resume(taskResult.taskId());
agentEngine.cancel(taskResult.taskId());

var tasks = agentEngine.listTasks(new TaskQuery(java.util.List.of(), java.util.List.of()), new PageRequest(0, 20));
TaskSummary first = tasks.items().isEmpty() ? null : tasks.items().get(0);

String markdownPath = agentEngine.export(taskResult.taskId(), ExportType.MARKDOWN);

运行模型

  • 运行时支持静态 DAG,也支持显式 @AgentFanOut / @AgentFanIn 的单层动态 fan-out / fan-in。
  • 当前仍不支持多层嵌套动态 fan-out / fan-in,或运行时生成任意子图。
  • step 间 typed 数据交换通过 StepExecutionResult + outputType + StepArtifacts 完成,不再依赖裸 Map<String, Object> 总线。
  • fan-in step 可通过 StepArtifacts.requireAll(stepCode, type) 读取某个 fan-out 逻辑 step 的全部实例输出。
  • fan-out 分支返回的 BUSINESS artifact 会自动保存为 artifactKey:<stepInstanceId>,避免多个分支写同一个业务 key 时互相覆盖。
  • TaskResult 是任务级稳定读取模型,typed final result 是它的上层投影能力。
  • 内置 exporter 默认不把 systemArtifacts 当成稳定交付内容;如果需要内部运行面数据,应通过 TaskResult 程序化读取。
  • 控制面状态来自结构化 task / step run 视图;动态 fan-out 时,StepRunView 会带 stepInstanceIdfanOutIndex
  • 事件是第一叙事通道;trace artifact 只作为可选调试或导出材料。
  • starter 通过 listener 方式接入 metrics / observation,不把观测逻辑硬编码进 engine。
  • 更完整的当前 runtime 合同与已知限制见 docs/runtime-contract-and-known-limitations.md

适用边界

  • 适合嵌入 Spring Boot 应用、单进程或受控实例内部运行的多步骤任务编排。
  • 适合需要结构化 task / step 状态、事件、导出和本地 AgentEngine 接入的场景。
  • 当前不适合作为要求“进程重启自动恢复在途任务”或“多实例共享统一控制面状态”的平台型运行时。

更明确的开源版支持边界见 docs/open-source-support-boundary.md

可运行示例

  • examples/minimal-memory-demo 最小内存示例,演示 typed result、静态 fan-out / fan-in 和 Markdown 导出。
  • examples/jpa-h2-demo 面向 H2 的 JPA 持久化示例,开箱即跑,演示 Flyway、失败后 retryStep(...)、typed result 和 JSON 导出。
  • examples/jpa-mysql-demo 面向 MySQL 的 JPA 持久化示例,直接使用 MySQL 配置与运行时依赖,不再通过 profile 切换数据库。
  • examples/dynamic-memory-demo 动态 fan-out / fan-in 示例,演示显式 @AgentFanOut / @AgentFanIn、typed result 和 Markdown 导出。

直接运行:

./mvnw clean install -DskipTests
./mvnw -f examples/minimal-memory-demo/pom.xml spring-boot:run
./mvnw -f examples/jpa-h2-demo/pom.xml spring-boot:run
CHARMFLOW_DB_URL='jdbc:mysql://localhost:3306/charmflow_agent?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC' \
CHARMFLOW_DB_USERNAME='root' \
CHARMFLOW_DB_PASSWORD='root' \
./mvnw -f examples/jpa-mysql-demo/pom.xml spring-boot:run
./mvnw -f examples/dynamic-memory-demo/pom.xml spring-boot:run

构建与验证

./mvnw -q test
./mvnw -pl charmflow-agent-benchmarks -am -DskipTests package
./mvnw -B -Prelease -DskipTests -Dgpg.skip=true -Dcentral.skipPublishing=true verify
./mvnw -B dependency-check:aggregate

社区与贡献

文档

About

CharmFlow Agent Runtime 是一个可嵌入 Spring Boot 应用的多步骤 Agent 执行框架。项目以 Starter 形式提供,把任务流程编排为结构化的“任务 -> 步骤”执行单元,并通过本地 `AgentEngine` 驱动执行。

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages