智能工作流 是 AI Skill Hub 本期精选Agent工作流之一。综合评分 8.0 分,整体质量较高。我们强烈推荐将其纳入你的 AI 工具库,帮助提升工作效率。
智能工作流 是一套完整的 AI Agent 自动化工作流方案。通过可视化的节点编排,将复杂的多步骤任务拆解为清晰的自动化流程,实现全程无人值守的智能处理。支持与数百种外部服务和 API 无缝集成,适合构建数据处理管线、业务自动化和 AI 辅助决策系统。
智能工作流 是一套完整的 AI Agent 自动化工作流方案。通过可视化的节点编排,将复杂的多步骤任务拆解为清晰的自动化流程,实现全程无人值守的智能处理。支持与数百种外部服务和 API 无缝集成,适合构建数据处理管线、业务自动化和 AI 辅助决策系统。
# 克隆仓库 git clone https://github.com/jessedrelick/agens cd agens # 查看安装说明 cat README.md # 按 README 完成环境依赖安装后即可使用
# 查看帮助 agens --help # 基本运行 agens [options] <input> # 详细使用说明请查阅文档 # https://github.com/jessedrelick/agens
# agens 配置说明 # 查看配置选项 agens --config-example > config.yml # 常见配置项 # output_dir: ./output # log_level: info # workers: 4 # 环境变量(覆盖配置文件) export AGENS_CONFIG="/path/to/config.yml"
Agens is an Elixir application designed to build multi-agent workflows with language models.
Drawing inspiration from popular tools in the Python ecosystem, such as LangChain/LangGraph and CrewAI, Agens showcases Elixir's unique strengths in multi-agent workflows. While the ML/AI landscape is dominated by Python, Elixir's use of the BEAM virtual machine and OTP (Open Telecom Platform), specifically GenServers and Supervisors, makes it particularly well-suited for these tasks. Agens aims to demonstrate how these inherent design features can be leveraged effectively.
⚠️ Breaking Changes: v0.2 Agens has changed significantly since the original 0.1 release (August 2024). The 0.2 line is a substantial redesign: - TheAgens.Agentmodule has been removed.agent_idsurvives as an opaque identifier used by a Serving'sc:Agens.Serving.load_context/2callback. -Agens.Job.Stephas been replaced byAgens.Job.Node. Jobs are now a list of Nodes, not sequences of Steps. - Routing is dynamic and lives on the Serving (viaAgens.Router), not on static step configuration. - Observability moved to theAgens.Backendbehaviour (default backends emit messages to the caller and write structured logs). - Tool calls are configured per-Node via the:toolsfield and executed by the Serving'sc:Agens.Serving.tool_call/3callback (now modeled after MCP tool calls).
Agens.Router behaviour. Routing is decided per-request from the running Agens.Message and structured outputs, rather than baked into static configuration.Nx.Serving / Bumblebee) from your Serving's c:Agens.Serving.handle_message/3 callback. Agens makes no provider assumptions.use Agens.Serving, limit: N). A flood of :run calls drains gracefully through bounded concurrency rather than overwhelming the LM provider or local pipeline.c:Agens.Serving.tool_call/3 callback; resources resolved via c:Agens.Serving.load_resource/3 before inference.c:Agens.Serving.handle_sub/3) or be dispatched as additional routed-to work after inference.{:route, node_id, count}, yield/aggregation with {:yield, node_id}, retry with LM-supplied reasons via {:retry, reason}, explicit termination via :end.Agens.Prefixes, or replace c:Agens.Serving.build_prompt/3 entirely for full control over how the running Agens.Message is rendered into the final system/user prompt.Agens.Backend behaviour to fan lifecycle events out to your own logging, persistence, or UI layer; defaults emit messages to the caller process and write structured logs.Telemetry.Metrics definitions in Agens.Metrics for Job/Node/Sub/Serving/tool/resource lifecycle, ready to feed a Prometheus/StatsD reporter.Agens.Job.Config.from_json/1, useful for runtime-loaded workflows or non-Elixir authoring.Add agens to your list of dependencies in mix.exs:
def deps do
[
{:agens, "~> 0.2.0"}
]
end
A multi-agent workflow with Agens has four moving parts: a Serving (the LM interface), a Router (routing logic on top of structured outputs), a Job (a graph of Nodes), and optional Backends (observability/persistence). Most workflows only need one Serving and one Router.
--- 1. Add the Agens Supervisor to your supervision tree
children = [
{Agens.Supervisor, name: Agens.Supervisor}
]
Supervisor.start_link(children, strategy: :one_for_one)
See Agens.Supervisor for more information.
--- 2. Define and start a Serving
A Serving wraps language model inference. Implement the Agens.Serving behaviour, use Agens.Serving, and call your LM of choice (HTTP API, Nx.Serving/Bumblebee pipeline, anything else) inside c:Agens.Serving.handle_message/3.
defmodule MyApp.Serving do
use Agens.Serving
use Agens.Router
alias Agens.{Message, Serving}
@impl Serving
def start(state), do: {:ok, state}
@impl Serving
def handle_message(_state, %Message{system: system, user: user}, schema) do
# Call your LM with the prepared system/user prompts + JSON schema, return
# `{:ok, parsed}` or `{:error, reason}`.
end
@impl Serving
def handle_result({:ok, %{"body" => body} = parsed}, _state, _msg) do
{:ok, %Serving.Result{body: body, outputs: Map.get(parsed, "outputs", %{})}}
end
def handle_result({:error, reason}, _state, _msg), do: {:error, reason}
# Router callbacks (see step 3)
@impl Agens.Router
def outputs(%Message{}), do: []
@impl Agens.Router
def resolve(%Message{}, _outputs), do: [:end]
end
{:ok, _pid} =
Agens.Serving.start(%Agens.Serving.Config{
name: :my_serving,
serving: MyApp.Serving
})
See Agens.Serving and examples/servings/ for reference Serving implementations.
--- 3. Define a Router
A Router maps a Serving's structured outputs to a list of routing instructions ({:route, node_id, count}, {:yield, node_id}, {:sub, job_id}, :end, :retry).
A Router can live in the Serving module itself (the "merged" pattern shown above) or in a dedicated module passed via use Agens.Serving, router: MyRouter (the "split" pattern — useful when many Servings share the same routing logic).
defmodule MyApp.LinearRouter do
use Agens.Router
alias Agens.Message
@impl Agens.Router
def outputs(%Message{}), do: []
@impl Agens.Router
def resolve(%Message{node_id: "summarize"}, _), do: [{:route, "critique", 1}]
def resolve(%Message{node_id: "critique"}, _), do: [:end]
end
For routing decisions that depend on the LM's structured response, declare an Agens.Router.Output schema and use Agens.Router.Condition to branch:
def outputs(%Message{}) do
[
%Output{key: "viable", type: "bool", description: "Is the topic researchable?"},
%Output{key: "confidence", type: "int", description: "1-10 confidence in the result"}
]
end
def resolve(_msg, outputs) do
cond do
Condition.check(%Condition{key: "viable", op: "eq", value: "false"}, outputs) -> [:end]
Condition.check(%Condition{key: "confidence", op: "lt", value: "7"}, outputs) -> [:retry]
true -> [{:route, "writer", 1}]
end
end
See Agens.Router, Agens.Router.Output, Agens.Router.Condition, and examples/router/ for more.
--- 4. Define and run a Job
A Job is a graph of Agens.Job.Nodes with a designated :starting_node_id. Each Node declares a Serving and, optionally, an agent_id, objective, tools, resources, or a sub Job. Routing between Nodes is decided at runtime by the Serving's Router — there is no static next field on a Node.
config = %Agens.Job.Config{
id: "summarize_critique",
description: "Summarize a topic in three sentences, then critique the summary.",
starting_node_id: "summarize",
nodes: %{
"summarize" => %Agens.Job.Node{
serving: :my_serving,
agent_id: "summarizer",
objective: "Write a tight three-sentence summary of the topic."
},
"critique" => %Agens.Job.Node{
serving: :my_serving,
agent_id: "critic",
objective: "Identify one weakness or omission in the summary."
}
}
}
run_id = Agens.generate_uid()
{:ok, _pid} = Agens.Job.start(config, run_id)
:ok = Agens.Job.run(run_id, "the rise of small open-weight LLMs", [])
Jobs are addressed by run_id (not name) so the same Job.Config can be executed in parallel. See Agens.Job, Agens.Job.Config, and Agens.Job.Node.
--- 5. Observe via Backends (optional)
The Agens.Backend behaviour fans out lifecycle and Node activity to one or more backends. Defaults are configured via the :backends application key:
config :agens, backends: [Agens.Backend.Emit, Agens.Backend.Log, MyApp.PubSubBackend]
The default emit backend sends {:job_run, _, _}, {:node_started, msg}, {:node_result, msg}, {:tool_call, msg, call}, {:resource_load, msg, resource}, {:job_complete, _} (natural completion) or {:job_ended, _} (explicit :end instruction), and more to the caller process — handle them with handle_info/2 in a LiveView or any GenServer. See Agens.Backend for the full list of callbacks.
--- Sub-Jobs
A Node can run an entire Sub-Job in place of inference by setting :sub to a Job id. When the Sub completes, the parent invokes the Node's Serving c:Agens.Serving.handle_sub/3 callback to map the Sub's final Agens.Message into the parent Node's outputs and routing decision. A Serving can also emit {:sub, job_id} in its next list to chain a Sub-Job after its own inference. See the "Routing and Sub-Jobs" section in Agens.Job for details.
The examples/ directory contains:
phoenix.exs — wiring up Instructor, MCP tools, a PubSub backend, and a multi-node routed Job.examples/servings/ (e.g. Instructor for structured outputs).examples/router/.examples/backends/.examples/mcp/ using hermes_mcp for tools and resources.examples/jobs/, loaded via Agens.Job.Config.from_json/1.Run the Phoenix example with:
elixir examples/phoenix.exs
It will be available at http://localhost:8080.
高质量的AI工作流项目
AI Skill Hub 为第三方内容聚合平台,本页面信息基于公开数据整理,不对工具功能和质量作任何法律背书。
建议在沙箱或测试环境中充分验证后,再部署至生产环境,并做好必要的安全评估。
✅ Apache 2.0 — 宽松开源协议,可商用,需保留版权声明和 NOTICE 文件,含专利授权条款。
经综合评估,智能工作流 在Agent工作流赛道中表现稳健,质量优秀。如果你已有明确的使用需求,可以直接上手体验;如果还在评估阶段,建议对比同类工具后再做决策。
| 原始名称 | agens |
| 原始描述 | 开源AI工作流:Create multi-agent workflows with AI and Language Models using OTP components in。⭐22 · Elixir |
| Topics | AI工作流Elixir智能体 |
| GitHub | https://github.com/jessedrelick/agens |
| License | Apache-2.0 |
| 语言 | Elixir |
收录时间:2026-05-26 · 更新时间:2026-05-26 · License:Apache-2.0 · AI Skill Hub 不对第三方内容的准确性作法律背书。
选择 Agent 类型,复制安装指令后粘贴到对应客户端