需自行准备模型服务与 API Key,示例用 ${ENV.DEEPSEEK_API_KEY} 从环境变量读取;本地 Ollama 需先 ollama pull 拉取模型;gVisor、Seatbelt、Landlock 等沙箱机制默认不启用,需显式选择并按需探测外部依赖
Agently
AgentEraApache-2.0活跃维护用结构化数据和链式调用语法在代码里快速搭建 GenAI 应用与智能体,并用事件驱动流程编排复杂逻辑,切换模型无需改代码。
[GenAI Application Development Framework] 🚀 Build GenAI application quick and easy 💬 Easy to interact with GenAI agent in code using structure data and chained-calls syntax 🧩 Use Event-Driven Flow *TriggerFlow* to manage complex GenAI working logic 🔀 Switch to any model without rewrite application code
pip install -U agentlyREADME 未说明;示例使用 DeepSeek 等 OpenAI 兼容云端接口,也可指向本地 Ollama(如 qwen2.5:7b)
用结构化输出和可观测 Action 构建可靠 AI 服务后端的 Python 运行时框架
用结构化数据和链式调用语法在代码里快速搭建 GenAI 应用与智能体,并用事件驱动流程编排复杂逻辑,切换模型无需改代码。
核心能力
- 用 .output 声明式 schema 保证结构化输出并自动重试校验
- instant 流式模式在生成中提前暴露结构化字段
- Action Runtime 统一本地函数、MCP 与沙箱执行并产出结构化记录
- Model Pool 与模型别名切换模型无需改业务代码
- Dynamic Task 把模型生成的 DAG 转成可校验任务图
容易踩的坑
- v4.1.4.10Agently 4.1.4.10最新正式版2026-10-13 · 2026-10-13 12:36 UTC
Long-task file Actions could succeed while the selected private file disappeared at terminal cleanup. Observations also lost file references, and implicitly inherited file Actions could bind to the Agent workspace identity instead of the current execution. This patch preserves observed file identities, validates exact file selections, and retains selected deliverables after close, including useful files from blocked runs.
execution = ( agent.create_execution("long_task") .input(task) .use_actions(["read_file", "write_file"]) .output({"files": [str], "summary": str}) ) result = await execution.async_get_data()Each file result must contain an exact path returned by the Action. Existing workspace permissions and explicit validation policies still apply.
Area Change Usage / compatibility Evidence Long-task delivery Preserve observed refs, execution identity and verified selected files Existing 4.1 API; unknown paths cannot create trusted identities Lifecycle, stale/missing file, pause/recovery/rework and binary-delivery regression tests; real installed-package file run Native file Actions Resolve implicitly inherited workspace at call time Explicit roots and isolated scope retain their boundaries Native writes and code-artifact readback tests FastMCP SDK 1/2 schema and tags, empty structured results, errors and wire aliases FastMCP 3/4, existing use_mcp; managed resource lifecycle unchangedReal SDK tests and stdio/HTTP/in-process calls on both lines Dependencies / typing Refresh lock within existing constraints; preserve open text-history and annotation behavior No 4.2 compatibility removals Full typing, Ruff, boundary tests, clean install and IDE smoke Release CI Python 3.10/3.14 × FastMCP 3/4 on PRs Publication restricted to main pushes/manual main runs Workflow gate tests; remote matrix required before promotion Deferred Semantic accuracy, business completion and comprehensive PDF visual quality No new default judge or unproven Prompt strategy; physical delivery does not certify content Explicit limits in bilingual release notes Published package: https://pypi.org/project/agently/4.1.4.10/
Validation: Python 3.10/3.14 × FastMCP 3/4, declared-minimum dependency startup/snapshots, typing, Ruff, frozen usage examples, Skills and released DevTools compatibility checks passed. Final release PR: https://github.com/AgentEra/Agently/pull/369. Automated publication: https://github.com/AgentEra/Agently/actions/runs/38396675118.
- v4.1.4.6Agently 4.1.4.62026-07-31 · 2026-07-31 11:52 UTC
查看更新说明
title: Agently 4.1.4.6 Release Notes description: Standard package version inspection, unified reasoning lifecycle events, and live TriggerFlow sub-flow resources. keywords: Agently, 4.1.4.6, version, reasoning, thinking, DeepSeek, Anthropic, Responses, TriggerFlow
Agently 4.1.4.6 Release Notes
Agently 4.1.4.6 is a focused compatibility patch over 4.1.4.5. It:
- exposes the package version through the standard
__version__spelling; - normalizes generated reasoning across OpenAI-compatible Chat Completions, Anthropic-compatible Messages, and Responses adapters;
- makes the public compatible-request retry policy the sole owner of physical SSE reconnection across Chat Completions, Anthropic Messages, and Responses;
- keeps live runtime resources live when they cross a TriggerFlow sub-flow boundary.
The sandbox-provider drafts tracked in #342 are not part of this release.
Core changes
Area What changed Recommended usage Compatibility / risk Evidence Package version Added the standard agently.__version__andAgently.__version__surfaces; removed the mistaken 4.1.4.5versionattributesInspect either __version__surfaceIntentional breaking correction only for code that adopted the mistaken 4.1.4.5 attributes Package/version tests, built wheel and clean-install smoke Compatible model reasoning Chat Completions, Anthropic Messages, and Responses now converge generated reasoning into reasoning_delta,reasoning_done, and provider-nativeoriginal_doneKeep provider controls in request_options; consume the public reasoning lifecycleAdditive response normalization; provider request options remain unchanged Adapter suites plus real deepseek-v4-flashChat Completions and Anthropic Messages probesCompatible SSE retry Removed hidden transport reconnects and made request_retry/AttemptRunnerthe sole physical-request retry owner across all three adaptersUse request_retry=Falseormax_attempts=1for one physical connection; useafter_output=Falsewhen provisional output cannot be resetDefault bounded replay remains; newly observable boundaries prevent uncounted requests and mixed output Physical-connection, retry-boundary, attempt-index, [DONE], and EDA TransportGuard regression testsTriggerFlow sub-flow resources Resource capture and isolated child templates preserve live runtime-resource object identity Pass clients, locks, callbacks, and services through resources; re-inject them after restoring a saved root executionResource capture is shared by identity; ordinary input/value capture remains copy-isolated TriggerFlow resource-identity tests and sub-flow foundation example Sandbox provider contributions No sandbox provider draft is merged in 4.1.4.6 Coordinate and consolidate the contributor work through issue #342 Explicitly deferred; no runtime or dependency change in this release Issue #342 and unchanged optional-provider surface Standard package version
Use either public version surface:
import agently from agently import Agently assert agently.__version__ == "4.1.4.6" assert Agently.__version__ == agently.__version__The mistakenly introduced
agently.versionandAgently.versionattributes from 4.1.4.5 are removed rather than retained as aliases.Unified reasoning lifecycle
Provider-specific request options remain under
request_optionsand pass through unchanged. For example, an OpenAI-compatible endpoint can receive:plugins: ModelRequester: OpenAICompatible: model: deepseek-v4-flash request_options: thinking: type: enabledGenerated reasoning is projected through the same public response lifecycle:
reasoning_deltacarries streamed reasoning increments;reasoning_donecarries the reconciled reasoning value exactly once;original_donere
- exposes the package version through the standard
- v4.1.4.5Agently 4.1.4.52026-07-30 · 2026-07-30 11:45 UTC
查看更新说明
title: Agently 4.1.4.5 Release Notes description: Opt-in long-output continuation and Stage-backed TriggerFlow task lifecycle ownership. keywords: Agently, 4.1.4.5, long output, TriggerFlow, Agently-Stage, settlement
Agently 4.1.4.5 Release Notes
Agently 4.1.4.5 strengthens two runtime boundaries without changing their semantic owners:
AgentExecutioncan opt into lossless continuation when a directModelRequestends with an observed length or incomplete terminal;TriggerFlowExecutionnow uses Agently-Stage as the direct owner of its process-local managed tasks instead of reproducing a second task scope.
Opt-in long-output continuation
Call
.ensure_long_output()on an unstarted directAgentExecutionwhen the business result must survive a provider response-window boundary:result = ( agent .input({"topic": "runtime ownership"}) .instruct("Write the complete technical report.") .ensure_long_output() .get_result() )The first request keeps its original prompt and output contract. Continuation starts only after an observed provider/parser terminal explicitly reports length or incomplete output. Accepted text or structured units are committed append-only, stored through
TaskWorkspace, read back, and validated against the original output contract before delivery.This policy is disabled by default. It supports plain text and declared JSON output contracts and cannot be combined with an explicit AgentTask strategy. Ordinary successful responses remain single-request executions.
See Output Control and
examples/basic/ensure_long_output.py.Stage-backed TriggerFlow task ownership
Agently now requires
agently-stage >=0.3.5,<0.4.0.Each
TriggerFlowExecutiondirectly owns one real Stage:- execution-created caller-loop tasks enter through
Stage.create_task(...); - genuinely pre-existing tasks enter through
Stage.adopt(...); - Stage is the single live task/origin inventory and settlement owner;
- TriggerFlow retains workflow failure policy, one close deadline, RuntimeEvent projection, and close snapshots.
The former private
StageManagedTaskScopeadapter has been deleted. This is not a public Stage API exposure through Agently: EventCenter, SignalNet, TriggerFlow, RuntimeEvent, and AgentExecution keep their existing semantic ownership.Hidden runtime-stream executions now close and settle explicitly after stream consumption, preventing an idle monitor from surviving the caller loop. EventCenter keeps its native background-task mechanism because replacing that hot path did not justify its measured overhead.
Sync/async compatibility
Agently's internal call-shape bridges use Agently-Stage
StageCallBridge.FunctionShifterremains importable as a deprecated compatibility facade and delegates to the same bridge; new framework code should not use it as a task lifecycle owner.Package version inspection
The package and the default
Agentlyfacade expose the same release version:import agently from agently import Agently assert agently.version == "4.1.4.5" assert Agently.version == agently.versionPerformance characterization
The Stage-native TriggerFlow candidate was compared with the previous private adapter in two reverse-order local runs, with 18 recorded samples per variant:
Workload Candidate delta Managed task create and settlement +4.74% (about +0.61 µs/task) Cancellation settlement -3.08% Finite TriggerFlow execution -1.34% TriggerFlow event fan-out +0.29% Peak traced task memory 0.00% No run emitted a pending-task, unconsumed-exception, or lifecycle warning. These numbers demonstrate bounded local overhead; they do not claim that Stage makes provider-bound model requests faster.
Core changes
| Area | What changed | Recommended usage | Compatibility / risk | Evidence | |---|
- v4.1.4.42026-07-25 · 2026-07-25 11:00 UTC
查看更新说明
Agently 4.1.4.4 Release Notes
Agently 4.1.4.4 strengthens two existing owner boundaries:
ModelRequestremains responsible for structured-output prompting and validation, while TriggerFlow and its configured persistence provider remain responsible for recoverable execution snapshots. No new facade or parallel runtime was added.Structured output constraints and correction
Pydantic v2 field constraints are now projected into supported structured-output prompt formats, including requiredness, nullability, aliases, enum/literal values, string and collection lengths, numeric ranges, patterns, and formats. The original model remains the final acceptance authority.
from pydantic import BaseModel, Field class Ticket(BaseModel): title: str = Field(min_length=3, max_length=80) priority: int = Field(ge=1, le=3) labels: list[str] = Field(min_length=1, max_length=5) ticket = ( agent .input("Turn this incident report into a triage ticket.") .output(Ticket, format="json") .get_result() .get_data_object() )If parsed data fails Pydantic validation, Agently sends bounded field-level correction feedback into the existing retry path. An invalid dictionary is not returned as successful business data, and an accepted retry remains reusable through object, data, and text result readers.
Recovery-aware TriggerFlow snapshots
Issue #331 showed that repeated save/load cycles could retain large completed signal values in every recovery snapshot. 4.1.4.4 adds an opt-in projection policy for eligible terminal values:
execution.set_snapshot_projection_policy( terminal_value_mode="digest", min_value_bytes=4096, )Pending interrupts and state required for recovery remain complete. Projected terminal values retain a canonical SHA-256 digest and encoded size so duplicate or conflicting resume requests can still be checked. Schema-v2 snapshots can load prior schema-v1 full-value snapshots.
The built-in local
RecordStorenow keeps the latest three execution snapshot versions perrun_idby default:record_store = RecordStore( "./recovery", snapshot_retention={"keep_last": 5}, ) execution.set_snapshot_retention_policy(keep_last=2) report = await execution.async_prune_recovery_snapshots(keep_last=1)Use
{"keep_last": None}to disable automatic pruning. Projection is owned by TriggerFlow because it understands recovery semantics; physical retention is owned by the persistence provider. Genericput_checkpoint(...)writes are not automatically pruned.Release validation policy
Default
pytestno longer depends on a locally running Ollama service or a pre-pulled Ollama model. Deterministic OpenAI-compatible protocol tests remain in the normal suite. Real-model release evidence is run separately against an explicitly configured online model so the provider, model, request count, and observed result can be recorded honestly.Core changes and upgrade impact
Area What changed Recommended usage Compatibility and risk Evidence Structured output Supported Pydantic field constraints enter prompts and validation failures enter bounded retries. Keep the BaseModelclass as the.output(...)contract.Additive correction of previously under-specified prompts; custom validators remain host-side only. Prompt-generator, validation, result-reuse, and typing tests. Snapshot projection TriggerFlow can digest eligible terminal interrupt values and completed resume metadata. Opt in for executions whose completed values dominate snapshot size. Full values remain the default; pending recovery data is never projected. Issue #331 A/B run: 1,307,086 B default versus 106,782 B digest projection, a 91.83% reduction. Snapshot retention The built-in local provider keeps the latest three versions by default. Configure provider defaults or an executi - v4.1.4.32026-07-25 · 2026-07-25 11:00 UTC
查看更新说明
Historical GitHub release record backfilled on 2026-07-25. The 4.1.4.3 package was originally published from commit
c4ee23009f70d543b9c56a28e6b9b14f9b053d64.Agently 4.1.4.3 Release Notes
Agently 4.1.4.3 is a focused compatibility patch for structured output. It preserves the public APIs and owner boundaries from 4.1.4.2.
Pydantic output models
Passing a Pydantic v2
BaseModelclass directly to.output(...)could fail during request initialization, before the provider was called. The prompt generator treated the class as a generic Python type and attempted to instantiate it without its required fields.4.1.4.3 recognizes
BaseModelclasses before generic type handling, recursively projects nested fields into the prompt schema, and preserves the original model class as the result model.class MeetingMinutes(BaseModel): topic: str decisions: list[Decision] minutes = ( agent .input(meeting_text) .output(MeetingMinutes, format="json") .get_result() .get_data_object() ) assert isinstance(minutes, MeetingMinutes)The same contract is supported by direct
ModelRequestusage andAgentExecution.output(...). Existing dictionary, tuple, JSON Schema, and explicit nested output descriptions remain supported.Validation
- Regression coverage includes direct requests, nested Pydantic models, and AgentExecution direct strategy.
- The release candidate was built as a wheel and installed into an isolated Python 3.10 environment before publication.
- The complete repository suite and static type gate passed for the underlying fix before release preparation.
Related issue: #329.
Compatibility
- Package version:
4.1.4.3. - Release manifest:
compatibility/releases/4.1.4.3.json. - Python:
>=3.10. - Recommended DevTools version remains
agently-devtools >=0.1.10,<0.2.0.
用户点评
登录用户的真实使用记录,可按版本和硬件筛选还没有人点评。第一个说出真实体验的人最有价值。
Agently 4.1.4.10 - AI Application Runtime Framework
Build AI service backends with structured outputs, observable Actions, runtime Skills, MCP capabilities, process streams, and recoverable workflows.
Who This README Is For
Agently is for teams moving from "the model can do it once" to "the application must do it reliably":
- product engineers building assistants, internal copilots, knowledge tools, operation workflows, or AI-backed APIs
- platform teams that need clear extension points for model providers, tools, MCP servers, sandboxes, workflows, and observability
- technical leads comparing AI frameworks for maintainability, explicit control, debuggability, and production handoff
- coding-agent users who want a framework whose recommended patterns can be encoded as reusable project guidance
The main design question is simple: how do you keep model behavior useful while still giving application code stable contracts, observable execution, and restart-safe workflow boundaries?
Agently 4.1.4.10 fixes long-task file delivery and supports FastMCP 3/4 while retaining the existing 4.1 APIs. Content accuracy and business completion judgment still require application-level review.
The existing one-run Agent composition remains available:
Actions and Skills preserve AgentExecution fluent typing, built-in Execution,
effort, strategy, Action protocol, and concurrency choices appear in IDEs, and
stable interaction, review, final validation, and artifact delivery APIs now have
complete examples. It also adds accepted retry-stream replay, fail-closed model
aliases, execution-scoped Skills, programmatic Action calling, and clearer
concurrent debug output. Read the
4.1.4.10 Release Notes, 4.1.4.9 Release Notes, 4.1.4.8 Release Notes,
4.1.4.7 Release Notes,
4.1.4.6 Release Notes,
4.1.4.5 Release Notes,
4.1.4.4 Release Notes,
4.1.4.3 Release Notes, and
4.1.4 Release Notes for the
current release and upgrade path.
Why Agently
Many AI frameworks are strong at exploration or at assembling broad integration stacks. Agently is optimized for the engineering layer that makes model applications survive model changes, output drift, streaming UX, action execution, workflow signals, and service boundaries.
Agently is a good fit when you care about:
- AI services should be runtime executions, not prompt glue -
AgentExecutionowns one run's prompt, strategy, Actions, Skill bindings, process stream, TaskContext evidence, and result views across direct, flat, and TaskBoard strategies. Read 4.1.4.8 Release Notes, 4.1.4 Release Notes, and Agent Auto Orchestration examples. - Model switching should not rewrite business logic - Agently normalizes provider setup, prompt slots, response parsing, action execution, and response reading into one request/runtime contract. Read Model Setup, Models Overview, and Requests Overview.
- Structured output should be a framework guarantee, not only a provider feature -
.output(...)schemas, required field extraction, parser feedback, retries,ensure_keys,ensure_all_keys, and validation handlers work together inside Agently. Read Schema as Prompt, Output Control, and examples inexamples/basic/. - Streaming should expose structure before the final token -
instantmode lets consumers react to structured fields while the model is still streaming, which is useful for UI updates, SSE routes, and workflow signals. Read Model Response, FastAPI Service Exposure, andexamples/fastapi/. - Actions should be observable and model-portable - local functions, built-in actions, MCP servers, shell/Python/Node/SQLite/TaskWorkspace helpers, and custom executors produce structured records and can share one Action Runtime. Read Action Runtime, MCP, and
examples/action_runtime/. - Skills should be immutable guidance, not a hidden execution route -
SkillLibraryowns installed revisions, AgentExecution owns selection and exact-revision binding, and TaskContext owns disclosure.Agently.skills_executorremains management/context compatibility only. Read Skills andexamples/skills_executor/. - Execution dependencies should have lifecycle owners - Execution Resource providers manage reusable resources such as MCP processes, browser sessions, shell/Python/Node runtimes, SQLite handles, and sandboxes. Built-in gVisor, Seatbelt, and Landlock candidates stay inactive until selected and probe their external mechanism on demand. Read Execution Resource and
examples/execution_resource/. - Generated plans should become validated task graphs - Dynamic Task turns model-generated or app-generated DAG data into validated, observable task execution through
Agently.create_dynamic_task(...). Read Dynamic Task andexamples/dynamic_task/. - Workflows should be signal-driven, not just graph-shaped - TriggerFlow supports events, fan-out, runtime streams, pause/resume, save/load, sub-flows, and close snapshots;
instantstructured output can become workflow input without waiting for the whole response. Read TriggerFlow Overview, Events and Streams, andexamples/trigger_flow/. - Common model-app patterns should be composable - router, To-Do/dependency execution, planning, reflection, evaluator/reviser, and multi-agent collaboration can be built from the same request/action/signal primitives. Read Playbooks, TriggerFlow Model Integration, and
examples/step_by_step/. - Services should keep clean project boundaries - async APIs, FastAPI helpers, settings files, prompt files, DevTools observation, and companion coding-agent skills fit non-trivial projects. Read Project Framework, FastAPI Service Exposure, and Observability.
Current framework version: 4.1.4.8.
Python: >=3.10.
Framework Positioning
The point is not that other frameworks are wrong. They choose different centers of gravity.
| Framework | Primary strength | Where Agently is intentionally different |
|---|---|---|
| LangChain | Broad integrations, prebuilt agents, and application building blocks | Agently is narrower and more system-shaped: provider adaptation, prompt slots, structured output, response parsing, action execution, settings, and observability are normalized in one request/runtime contract. See Requests, Action Runtime, and examples/action_runtime/. |
| LangGraph | Low-level orchestration runtime for long-running, stateful agents | TriggerFlow is the orchestration layer inside Agently's model-application stack: workflow signals compose directly with structured response events, actions, runtime streams, pause/resume, execution state, and close snapshots. See TriggerFlow Events and Streams, Persistence and Blueprint, and examples/trigger_flow/. |
| CrewAI | Multi-agent crews plus flow-controlled agent teamwork | Agently treats multi-agent collaboration as one buildable pattern on top of lower-level request, action, signal, and workflow primitives, not as the only application shape. See Playbooks and examples/step_by_step/. |
| AutoGen | Conversable agents and multi-agent conversation patterns | Agently emphasizes model-output contracts, explicit action logs, signal-driven workflows, lifecycle snapshots, and service-facing execution handles over open-ended agent chat as the default boundary. |
| Direct SDK calls | Maximum control with minimal abstraction | Agently adds reusable contracts for output parsing, actions, sessions, configuration, observability, and workflows without forcing a separate orchestration service. |
Use Agently when the application needs an AI execution substrate. Stay closer to direct SDK calls when the product is only one or two simple prompts. Use a specialized multi-agent framework when natural-language agent collaboration is the main product primitive.
The practical differences show up in four layers:
- Against LangChain's integration-first style: LangChain is strong when you want a broad, flexible set of model, tool, retrieval, and agent building blocks. Agently's bet is that production model apps need a more uniform request contract: different model providers should still feed the same prompt slots, structured parser, retry/validation path, reusable result readers, and Action Runtime. That reduces the chance that swapping the base model or provider changes the shape expected by downstream business logic. Start with Requests Overview and Action Runtime.
- Against provider-native structured output as the only guarantee: Agently can use model providers, but its output quality path does not depend only on provider-side JSON schema or tool-calling parameters. The framework owns schema-as-prompt authoring, required-field extraction, parser feedback, retries,
ensure_keys,ensure_all_keys, and validation handlers. That matters when the target model does not expose the same structured-output or tool-calling semantics as another provider. See Schema as Prompt and Output Control. - Against graph-only orchestration: LangGraph is strong for graph-shaped stateful agents and durable execution. TriggerFlow's core is event/signal-driven, and Agently's
instantresponse mode can surface structured fields while the model is still streaming. That lets workflow signals be driven by partial structured output, action results, human input, or sub-flow state instead of waiting for a whole model response to finish. See Model Response, TriggerFlow Events and Streams, andexamples/fastapi/for streaming/service patterns. - Against treating multi-agent as the framework root: Multi-agent collaboration is useful, but in Agently it is a scenario you can build on top of requests, Actions, TriggerFlow signals, sub-flows, Session, and runtime resources. Router, To-Do/dependency execution, planning, reflection, evaluator/reviser, and agent-team patterns are all compositions over the same lower-level engineering substrate. See Playbooks, TriggerFlow Model Integration, and
examples/step_by_step/.
Quickstart
Install:
pip install -U agently
Use DeepSeek or another OpenAI-compatible hosted endpoint:
from agently import Agently
Agently.set_settings(
"OpenAICompatible",
{
"base_url": "https://api.deepseek.com/v1",
"model": "deepseek-v4-flash",
"api_key": "${ENV.DEEPSEEK_API_KEY}",
"model_type": "chat",
"request_options": {
"thinking": {"type": "disabled"},
"temperature": 0.2,
},
},
)
agent = Agently.create_agent()
result = (
agent
.input("Introduce Python in one sentence and state three distinct strengths.")
.output({
"intro": (str, "one sentence", True),
"strengths": {
"first": (str, "first strength", True),
"second": (str, "second strength", True),
"third": (str, "third strength", True),
},
})
.get_result()
)
print(result.get_data())
Use local Ollama by changing provider settings:
ollama pull qwen2.5:7b
Agently.set_settings(
"OpenAICompatible",
{
"base_url": "http://127.0.0.1:11434/v1",
"model": "qwen2.5:7b",
"api_key": "ollama",
"model_type": "chat",
},
)
Use a Model Pool when the same application needs multiple models:
Agently.set_settings("model_pool", {
"support-chat": "deepseek-v4-flash-prod",
"reasoning": "deepseek-reason-prod",
})
Agently.set_settings("model_profiles", {
"deepseek-v4-flash-prod": {
"provider": "OpenAICompatible",
"base_url": "https://api.deepseek.com/v1",
"model": "deepseek-v4-flash",
"api_key_pool": "deepseek-prod",
"request_options": {"thinking": {"type": "disabled"}},
},
"deepseek-reason-prod": {
"provider": "OpenAICompatible",
"base_url": "https://api.deepseek.com/v1",
"model": "deepseek-v4-flash",
"api_key_pool": "deepseek-prod",
"request_options": {
"thinking": {"type": "enabled"},
"reasoning_effort": "high",
},
},
})
Agently.set_settings("api_key_pools", {
"deepseek-prod": {
"selection": {"strategy": "round_robin"},
"failover": {
"strategy": "try_next",
"max_attempts": 2,
"retry_status_codes": [401, 403, 429],
},
"keys": [
{"id": "a", "value": "${ENV.DEEPSEEK_API_KEY_A}"},
{"id": "b", "value": "${ENV.DEEPSEEK_API_KEY_B}"},
],
},
})
agent.activate_model("reasoning")
activate_model(...) changes the default model key for subsequent Agent-owned
requests. Use agent.create_request(model_key="support-chat") for a one-off
override.
For file-backed settings, prefer:
from agently import Agently
Agently.load_settings("yaml_file", "settings.yaml", auto_load_env=True)
Core Capabilities
1. Structured Requests
Prompts are composed from named slots. That keeps application intent, constraints, context, and output contracts reviewable:
result = (
agent
.role("You are a concise release-note writer.")
.info({"version": "4.1.4.8", "audience": "framework users"})
.instruct("Return only facts grounded in the input.")
.input("Summarize this release line for an engineering changelog.")
.output({
"headline": (str, "short headline", True),
"bullets": [(str, "one stable fact")],
})
.get_result()
)
data = result.get_data()
full_data = result.get_full_data()
text = result.get_text()
meta = result.get_meta()
Use get_result() when the same model call will be inspected in more than one
way. For AgentExecutionResult, get_data() returns the business result across
direct, flat, and TaskBoard strategies; use get_full_data() only when the
caller needs the full route/task envelope. get_text() remains the user-facing
final-text view.
2. Contract-First Output Control
Fixed required leaves belong directly in .output(...) as the third tuple item:
ticket = (
agent
.input("The billing export fails for accounts with archived invoices.")
.output({
"category": (str, "billing / auth / data / unknown", True),
"severity": (int, "1-5", True),
"next_actions": [(str, "recommended action")],
})
.start()
)
Use ensure_keys= for conditional or runtime-dependent paths. Use .validate(...) or validate_handler= for value-level business rules. Use ensure_all_keys=True when the whole schema must be present.
YAML and JSON prompt files can carry the same contract through $ensure: true, so teams can review prompt and response shape outside Python code.
3. Structured Streaming
Instant events let a UI, service, or downstream consumer react as each structured field changes:
result = (
agent
.input("Explain recursion with two examples.")
.output({
"definition": (str, "one sentence", True),
"examples": [(str, "example with explanation")],
})
.get_result()
)
for event in result.get_generator(type="instant"):
if event.path == "definition" and event.delta:
print(event.delta, end="", flush=True)
if event.wildcard_path == "examples[*]" and event.is_complete:
print("\nEXAMPLE:", event.value)
This is useful for dashboards, chat UIs, SSE responses, and workflows that need partial structured results before the final response is complete.
Treat instant updates as provisional. Use get_data() / async_get_data()
when the caller does not publish or parse progressive fields; draining an
instant generator without consuming its updates only wastes work. Final
validation must complete before irreversible side effects or business
decisions.
4. Actions and Tool Use
Actions are model-callable capabilities. New code should start with @agent.action_func and agent.use_actions(...):
from agently import Agently
agent = Agently.create_agent()
@agent.action_func
def calculate_total(price: float, quantity: int) -> float:
"""Calculate an order total."""
return price * quantity
agent.use_actions(calculate_total)
result = (
agent
.input("Use the available action to calculate 19.5 * 4, then explain the result.")
.get_result()
)
print(result.get_text())
full_data = result.get_full_data()
print(full_data.get("extra", {}).get("action_logs", []))
Common capability helpers:
agent.enable_python()
agent.enable_shell(root=".", commands=["pwd", "rg"])
agent.enable_workspace(root=".", read=True, write=False)
agent.enable_nodejs()
agent.enable_sqlite(database="app.db")
Built-in action packages:
from agently.builtins.actions import Browse, Search
agent.use_actions(Search(timeout=15, backend="duckduckgo"))
agent.use_actions(Browse())
Use agent.use_mcp(...) for MCP servers. Use agent.register_action(..., executor=..., execution_resources=[...]) when building a custom backend with explicit managed resources.
Instruction-heavy actions keep later model context compact with execution digests and artifact references. The application can read raw artifacts explicitly when it needs full code, shell output, page content, SQL rows, screenshots, or logs:
turn = agent.input("Use the shell action and summarize the result.")
records = agent.get_action_result(prompt=turn.prompt)
artifact_ref = records[0]["artifact_refs"][0]
raw = agent.action.read_action_artifact(
artifact_id=artifact_ref["artifact_id"],
action_call_id=artifact_ref["action_call_id"],
)
The older tool_func / use_tools / use_mcp / use_sandbox family remains a compatibility surface, but new examples use actions.
5. Runtime Skills
Skills are reusable task guidance packages. In the current release, SkillLibrary owns
immutable installed revisions, AgentExecution owns selection and exact-revision
binding, and TaskContext owns progressive disclosure. agent.use_skills(...)
is the normal candidate-binding surface; agent.require_skills(...) binds a
known exact revision. Agently.skills_executor remains a thin compatibility
facade for installation, inspection, and context projection. In 4.1.4.8, as in
4.1.4.7, its legacy TaskDAG skill resolver helper is not an executor-ready
integration: it still needs a host adapter from the real TaskDAGContext before
node selectors reach the compatibility projection.
result = (
agent
.use_skills(
[
{"source": "GarethManning/education-agent-skills"},
{"source": "anthropics/skills", "subpath": "skills/docx"},
{"source": "anthropics/skills", "subpath": "skills/pptx"},
{"source": "anthropics/skills", "subpath": "skills/xlsx"},
],
mode="model_decision",
)
.goal(
"Create a four-week B1 business English course package.",
["Include a course plan, teacher guide, and progress tracker"],
)
.effort("medium")
.output({
"course_plan": (dict, "course goals and weekly structure", True),
"teacher_guide": (str, "teacher-facing guide summary", True),
"progress_tracker": ([str], "tracking columns and checkpoints", True),
})
.get_result()
)
data = await result.async_get_data()
Business value: reusable Skills can turn a model call into a deliverable business process such as an education package, research memo, QA evidence pack, travel plan, or operational review. Application code stays focused on business inputs and output contracts instead of cloning remote repositories, parsing Skill files, or manually wiring each tool.
Skill capability requirements do not authorize side effects by themselves. Host code must explicitly mount the required Actions, MCP services, or ExecutionResource providers and apply policy before execution. Unavailable, ambiguous, low-confidence, or policy-denied capabilities fail closed with diagnostics; side effects remain owned by Action Runtime, ExecutionResource, TaskWorkspace, RecordStore, or TriggerFlow.
6. TriggerFlow Orchestration
TriggerFlow is Agently's workflow layer for explicit stages, branching, fan-out, event-driven input, runtime streams, pause/resume, persistence, and restart-safe execution.
import asyncio
from agently import TriggerFlow, TriggerFlowRuntimeData
flow = TriggerFlow(name="ticket-flow")
async def classify(data: TriggerFlowRuntimeData):
text = data.input["text"]
category = "billing" if "invoice" in text.lower() else "unknown"
await data.async_set_state("category", category)
return category
async def route(data: TriggerFlowRuntimeData):
category = data.input
await data.async_set_state("handler", f"{category}-team")
flow.to(classify).to(route)
async def main():
execution = flow.create_execution()
await execution.async_start({"text": "Invoice export failed."})
snapshot = await execution.async_close()
print(snapshot)
asyncio.run(main())
For services, workers, webhooks, human review, or SSE/WebSocket routes, keep the execution handle and close it explicitly:
execution = flow.create_execution(auto_close=False)
await execution.async_start(initial_input)
await execution.async_emit("UserApproved", {"approved": True})
snapshot = await execution.async_close()
close() / async_close() is the canonical completion path in the 4.1 line. The close snapshot is the durable result contract.
TriggerFlow is the right tool when you need:
| Need | TriggerFlow surface |
|---|---|
| Branches based on intermediate results | if_condition, elif_condition, else_condition, match, case |
| Parallel work over many items | for_each(concurrency=...), batch(...) |
| External events or human review | when(...), emit(...), pause_for(...), continue_with(...) |
| Live UI or service output | runtime stream APIs |
| Restart safety | save(...), load(...), close snapshots |
| Reusable workflow topology | blueprint export/import |
For complex services, map real serial and parallel dependencies before writing the flow. Run independent work concurrently and expose pressure controls where they are owned: host in-flight coroutine limits, TriggerFlow execution and fan-out concurrency, model rate/concurrency limits, and thread-pool sizes for blocking code.
7. Dynamic Task
Dynamic Task is Agently's convenience surface for model-generated or
application-submitted DAG data; TaskDAG owns planning, validation, resolution,
and execution. It is an application API, not a TriggerFlow sub-API. By default,
TaskDAGExecutor.async_run(...) compiles the validated DAG directly to the
TriggerFlow substrate. Blocks compilation is an explicit opt-in path when the
caller needs Blocks lifecycle evidence or ExecutionBlockGraph output.
from agently import Agently
async def local_handler(context):
return {"task_id": context.task.id, "deps": dict(context.dependency_results)}
task = Agently.create_dynamic_task(
target="review policy",
plan={
"graph_id": "review",
"task_schema_version": "task_dag/v1",
"tasks": [
{"id": "extract", "kind": "local", "binding": "local_handler"},
{"id": "final", "kind": "local", "binding": "local_handler", "depends_on": ["extract"]},
],
"semantic_outputs": {"final": "final"},
},
handlers={"local_handler": local_handler},
)
snapshot = await task.async_start(timeout=10)
Use Dynamic Task when the task plan itself is data that needs planning, validation, pruning, and execution. Never compile unvalidated runtime plan data directly into new TriggerFlow definitions. Use TriggerFlow directly when you own a stable workflow topology in trusted source code.
8. Session Memory
Session keeps bounded multi-turn state when the problem is still one conversational thread, not a full workflow:
agent.activate_session(session_id="user-42")
agent.set_settings("session.max_length", 10000)
reply1 = agent.input("My name is Alice.").start()
reply2 = agent.input("What is my name?").start()
For long-running processes, event waits, fan-out, or human approvals, put TriggerFlow above the request layer instead of stretching Session into a workflow store.
9. Knowledge, Services, and Observability
Agently includes integration surfaces around the request and workflow layers:
- Knowledge base helpers for retrieval-backed context.
FastAPIHelperfor POST, SSE, and WebSocket exposure of agents, requests, generators, TriggerFlow definitions, and TriggerFlow executions.- Observation events for request, action, execution environment, and TriggerFlow internals.
- Optional
agently-devtoolsfor local observation, evaluation, playground workflows, and project scaffolding.
pip install agently-devtools
agently-devtools init my_project
Agently 4.1.4.8 recommends agently-devtools >=0.1.11,<0.2.0.
Architecture
Layer Model
Agently organizes AI application code into explicit layers. The layers can be used independently, but they are designed to compose:
graph TB
App["Application and business logic"]
Settings["Settings files and environment"]
Execution["AgentExecution: direct / flat / TaskBoard"]
Request["ModelRequest: prompt and output control"]
Model["Model requester plugins"]
Result["AgentExecutionResult / ModelRequestResult"]
Skills["SkillLibrary + AgentExecution\nimmutable revision binding"]
Action["Action Runtime: planning, dispatch, logs"]
Env["Execution Resource: MCP, Python, Bash, Node, Browser, SQLite"]
Context["TaskContext / ContextReader\ntask information and disclosure"]
TaskFiles["TaskWorkspace\ntask files and execution grants"]
Records["RecordStore\nrecords, checkpoints, snapshots, events"]
DAG["TaskDAG / DynamicTask\nvalidated acyclic plan data"]
Flow["TriggerFlow: branch, fan-out, stream, pause/resume, persist"]
Observe["RuntimeEvents and DevTools"]
App --> Settings
App --> Execution
Settings --> Execution
Execution --> Request
Request --> Model
Model --> Result
Execution --> Result
Execution --> Skills
Execution --> Action
Execution --> Context
Execution --> TaskFiles
Execution --> Records
Action --> Env
Action --> TaskFiles
App --> DAG
DAG --> Flow
App --> Flow
Flow --> Records
Flow --> Execution
Execution --> Observe
Action --> Observe
Env --> Observe
Flow --> Observe
Action Stack
Action Runtime separates planning, loop orchestration, backend execution, and managed resource lifecycle:
graph LR
Agent["Agent"]
Facade["Action facade"]
Runtime["ActionRuntime plugin\nplanning and call normalization"]
Flow["ActionFlow plugin\naction loop and orchestration bridge"]
Executor["ActionExecutor plugin\nfunction, MCP, sandbox, Search/Browse, custom"]
Env["ExecutionResourceProvider\nresource lifecycle"]
Logs["action_logs and artifacts"]
Agent --> Facade
Facade --> Runtime
Runtime --> Flow
Flow --> Env
Flow --> Executor
Executor --> Logs
Extension points:
| Layer | Extension point |
|---|---|
| Agent | custom agent extension and lifecycle hooks |
| Agent execution | strategies, lifecycle, result views, TaskContext evidence |
| Request | prompt generator, model requester, response parser |
| Actions | ActionRuntime, ActionFlow, ActionExecutor |
| Managed resources | ExecutionResourceProvider |
| Dynamic DAG | TaskDAG planner, validator, resolver, executor; DynamicTask facade |
| Workflow | TriggerFlow chunks, conditions, events, runtime stream, persistence |
| Observation | event hookers, sinks, DevTools bridge |
Project Shape
For anything beyond a small script, keep settings, prompts, actions, flows, and service code separate:
my-agently-app/
pyproject.toml
.env
settings.yaml
prompts/
summarize.yaml
triage.yaml
app/
agents.py
actions.py
api.py
main.py
flows/
triage.py
tests/
test_triage_flow.py
settings.yaml:
plugins:
ModelRequester:
OpenAICompatible:
base_url: ${ENV.OPENAI_BASE_URL}
api_key: ${ENV.OPENAI_API_KEY}
model: ${ENV.OPENAI_MODEL}
debug: false
Load at startup:
from agently import Agently
Agently.load_settings("yaml_file", "settings.yaml", auto_load_env=True)
Prompt files can carry prompt slots and output contracts:
.request:
instruct: |
You are a concise editor. Keep facts intact.
output:
title:
$type: str
$ensure: true
body:
$type: str
$ensure: true
Examples
Recommended model-app examples call a real model through DeepSeek or local Ollama and include an Expected key output source comment with stable key values from one real run.
Useful entry points:
| Directory | Use it for |
|---|---|
examples/cookbook/ | model-backed application patterns |
examples/agent_auto_orchestration/ | one Agent turn coordinating Actions, Skills, Dynamic Task, and process streams |
examples/skills_executor/ | remote Skills, effort-aware planning, MCP/script mounting, and model pool examples |
examples/action_runtime/ | function, MCP, sandbox, and plugin action examples |
examples/execution_resource/ | managed Python, shell, Node, SQLite, Browser, and provider lifecycle examples |
examples/dynamic_task/ | validated Dynamic Task DAG planning and execution examples |
examples/trigger_flow/ | focused TriggerFlow mechanics |
examples/builtin_actions/ | Search/Browse package examples |
examples/fastapi/ | service exposure examples |
examples/devtools/ | optional DevTools observation examples |
examples/release_pinned_usage/ | release-pinned developer usage checks; selected scripts require maintainer confirmation before usage-shape edits |
Archived examples live under examples/archived/ and are compatibility references, not the recommended starting point for new apps.
Ecosystem
Agently Skills
Agently-Skills gives coding agents current Agently implementation guidance.
- Repository: https://github.com/AgentEra/Agently-Skills
- Current catalog generation:
v3 - Recommended bundle:
app - Agently 4.1.4.8 compatibility: Skills authoring protocol
agently-skills.authoring.v3
Use it when asking Codex, Claude Code, Cursor, or another coding agent to implement Agently patterns.
Agently DevTools
agently-devtools is optional and covers local observation, evaluation, interactive wrappers, and project scaffolding.
pip install agently-devtools
agently-devtools init my_project
Integrations
| Integration | What it enables |
|---|---|
agently.integrations.chromadb | ChromaCollection knowledge-base workflows |
agently.integrations.fastapi | POST, SSE, and WebSocket service exposure |
| OpenAI-compatible requester | OpenAI, DeepSeek, Qwen, Ollama, Kimi, GLM, MiniMax, Doubao, SiliconFlow, Groq, ERNIE, Gemini-via-OpenAI |
| Anthropic-compatible requester | Claude through Anthropic's native API |
FAQ
What makes Agently different from direct SDK calls?
Direct SDK calls are excellent when the app only needs a small number of prompts. Agently adds contracts around those calls: prompt slots, output parsing, validation, retries, response reuse, action logs, session memory, configuration, service helpers, and TriggerFlow.
How is Agently different from LangChain?
LangChain provides broad integrations, prebuilt agents, and flexible building blocks. Agently is narrower and more opinionated about the model request boundary: provider setup, prompt slots, structured output, parser feedback, retries, validation, response reuse, action execution, settings, and observability are designed to line up as one contract. The goal is to let teams change the underlying model or provider without forcing downstream business logic to relearn output or tool-call shape.
How is Agently different from LangGraph?
LangGraph is strong when the central problem is graph-based agent state and durable execution. TriggerFlow is designed as Agently's signal-driven workflow layer: model-side instant structured events, action results, external events, pause/resume, runtime stream items, execution state, and close snapshots can all participate in the same orchestration story.
How is Agently different from CrewAI or AutoGen?
CrewAI and AutoGen are strong choices when the primary design is collaboration among agents. Agently is a lower-level application framework: multi-agent collaboration can be built as one pattern on top of structured model requests, Actions, TriggerFlow signals, sub-flows, Session, runtime resources, and service-facing execution handles.
Do I need TriggerFlow for every multi-step task?
No. Use plain Python or async functions for simple linear work. Use TriggerFlow when you need branches, fan-out, external events, pause/resume, runtime stream, persistence, or restart-safe execution.
Can I keep using older tool APIs?
Yes. The old tool family remains a compatibility surface and maps into the current action runtime. New code should prefer @agent.action_func, agent.use_actions(...), and the enable_* helpers.
How do I deploy an Agently service?
Use the async request APIs directly or wrap agents, requests, generators, TriggerFlow definitions, or TriggerFlow executions with FastAPIHelper. See the FastAPI docs and examples/fastapi/.
Documentation
Compatibility Notes
- The current package version is
4.1.4.8. - The current release manifest is
compatibility/releases/4.1.4.8.json. - Development-line planning belongs in
compatibility/in-development.json; do not treat planned future versions as released. AgentExecutionResult.get_data()returns business data; callers that need status, TaskBoard, diagnostics, or other route/task internals useget_full_data().- An explicitly captured
AgentExecutionrepresents one run. Create a fresh execution for the next request after it starts. - README examples use the current AgentExecution result, Action, TaskDAG, and TriggerFlow lifecycle paths.
- Deprecated APIs emit warnings once per Python process unless
runtime.show_deprecation_warningsis disabled.
Community
- Discussions: https://github.com/AgentEra/Agently/discussions
- Issues: https://github.com/AgentEra/Agently/issues
- WeChat group: https://doc.weixin.qq.com/forms/AIoA8gcHAFMAScAhgZQABIlW6tV3l7QQf
- Twitter / X: https://x.com/AgentlyTech
License
Agently follows an open-core model:
- Open-source core: Apache 2.0
- Trademark usage policy: TRADEMARK.md
- Contributor rights agreement: CLA.md
- Enterprise extensions and services: separate commercial agreements