Agently documentation for building AI applications with stable outputs, observable actions, and durable workflows.
Languages: English · 中文
Agently separates stable framework contracts from default implementations and developer-facing shortcuts.
Use this rule when designing or extending a capability:
Core contract
-> plugin/provider implementation
-> built-in capability Action
-> Agent Component or enable_* syntax sugar
-> business application
This order is a framework rule, not only a mental model. Before adding a feature, decide which layer owns the stable contract, which plugin/provider owns replaceable implementation behavior, and which Agent Component or facade owns the user-facing shortcut.
| Audience | What to use first | What to avoid |
|---|---|---|
| App developers | agent.use_actions(...), agent.use_mcp(...), built-in actions, future agent.enable_* helpers |
Direct manager/provider APIs unless the app owns the environment lifecycle |
| Action developers | register_action(...), custom ActionExecutor, execution_environments=[...] |
Starting long-lived sandboxes, MCP clients, processes, or services inside an executor |
| Plugin developers | ExecutionEnvironmentProvider, ActionExecutor, ActionRuntime, ActionFlow plugin contracts |
Coupling plugin code to one app-level shortcut |
| Framework maintainers | Core data types, managers, dispatch paths, compatibility rules | Putting product-specific behavior into core |
Core defines stable abstractions and lifecycle contracts. It should stay small.
Core owns:
Core should not directly become the feature catalog. For example,
ExecutionEnvironmentManager should know how to manage an environment
requirement, but it should not be the user-facing API for “do coding work in my
repo”.
Core also should not own plugin output prompts, provider-specific defaults, or Agent Component convenience behavior when a lower layer already has a contract for them. Plugins can import core contracts; core cannot depend on built-in plugin or Agent Component implementations.
Plugins implement replaceable backend behavior behind core contracts.
Examples:
ExecutionEnvironmentProvider for Python, Bash, Node.js, Docker, MCP, SQLite,
vector stores, browsers, or remote runners.ActionExecutor for one atomic action call.ActionRuntime for action planning and loop behavior.ActionFlow for execution strategy.Provider code owns environment-specific startup, health check, and release. It does not own app-level decisions about whether an agent should be allowed to use that environment.
Do not introduce parallel nouns such as ActionProvider,
CapabilityProvider, or a standalone capability dispatcher for this layer.
Callable ability remains Action; execution variation belongs to
ActionExecutor; live resource lifecycle belongs to ExecutionEnvironmentProvider.
Built-ins are the default capability catalog shipped by Agently. They expose model-callable operations as Actions and may depend on Execution Environment.
Good built-in candidates:
Action is the model-visible callable surface. Execution Environment is only used when the action needs a managed live dependency, isolation boundary, reusable client, or cleanup policy.
Built-in capability packages use agently.builtins.actions as the primary
authoring/import path and implementation home. agently.builtins.tools is a
thin legacy facade for existing code and should not be treated as the new
authoring layer.
Agent Components should provide scenario-level shortcuts for application developers. They compose built-in actions, policies, prompt guidance, and environment requirements.
Expected shape:
agent.enable_python(...)
agent.enable_shell(...)
agent.enable_workspace_file_actions(...)
agent.enable_nodejs(...)
agent.enable_sqlite(...)
agent.enable_vector_store(...)
agent.enable_coding_workspace(...)
These APIs should describe developer intent. They should not force app
developers to understand ExecutionEnvironmentHandle, provider lifecycle, or
executor internals.
Public APIs should expose constrained semantics through typing whenever
practical. Use Literal for finite option sets, TypedDict or dataclasses for
structured payloads, Protocol for plugin contracts, and precise union types
instead of bare str or dict when values have a known shape.
Typing is part of developer experience and API stability. For example, an option
such as desc_mode should be typed as Literal["append", "override",
"default"], while runtime validation should remain for untyped or dynamic
callers.
Core and builtins capabilities can be implemented as subdirectory packages. Prefer that shape when a feature has multiple architectural roles, such as a facade, manager, default implementation, registry, adapter, policy, or validation layer.
Do not default new core or builtins work to a single file. First judge the feature’s expected submodule volume and ownership boundaries. A single file is appropriate only when the capability is genuinely small and splitting it would be over-design.
Landed examples include core/Action, core/TriggerFlow,
core/TaskDAGExecutor, core/Workspace,
builtins/plugins/ExecutionEnvironmentProvider, and
builtins/plugins/SkillsExecutor. Keep public imports stable through package
__init__.py files and top-level re-exports.
Action and Execution Environment are separate layers.
Action answers:
ActionResult?Execution Environment answers:
Not every Action needs Execution Environment. File policy checks, pure local functions, and simple stateless operations can be plain Actions. Use Execution Environment when lifecycle, isolation, health, credentials, or cleanup matters.
Skills should not be a parallel executor.
A skill package may declare guidance, scripts, MCP assets, hooks, resources, or workflow templates. The Skills layer should resolve those declarations into a plan, then apply them to existing Agently layers:
This keeps Skills useful for packaging and selection without making them a second Action Runtime.
If a document explains how to use a capability in an app, put it near the
capability docs. If it explains ownership boundaries or extension rules, put it
under architecture/.
Examples:
actions/: how to expose callable operations to a model.triggerflow/: how to orchestrate multi-step work.observability/: how to observe and debug.architecture/: who owns which layer and where extensions belong.