mirror of
https://github.com/langgenius/dify.git
synced 2026-05-13 06:03:15 -04:00
refactor the docs of agenton
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
# Dify Agent
|
||||
|
||||
Agenton documentation lives in [`docs/agenton/`](docs/agenton/).
|
||||
Agenton documentation lives in [`docs/agenton/guide/`](docs/agenton/guide/) and
|
||||
[`docs/agenton/api/`](docs/agenton/api/).
|
||||
|
||||
@@ -1,88 +1,6 @@
|
||||
# Agenton configuration and sessions
|
||||
# Agenton documentation
|
||||
|
||||
Agenton composes shared `Layer` instances into a named graph. Treat layer
|
||||
instances as reusable capability definitions: config and dependency declarations
|
||||
belong on the layer class or instance, while per-session runtime values belong
|
||||
on the `LayerControl` created for that layer in a `CompositorSession`.
|
||||
|
||||
## Config, runtime state, and runtime handles
|
||||
|
||||
- **Config** is serializable graph input. Config-constructible layers declare a
|
||||
`type_id` and a Pydantic `config_type`; builders validate node config before
|
||||
calling `Layer.from_config(validated_config)`.
|
||||
- **Runtime state** is serializable per-layer/per-session state. Layers declare a
|
||||
Pydantic `runtime_state_type`; session snapshots persist this model with
|
||||
`model_dump(mode="json")`.
|
||||
- **Runtime handles** are live Python objects such as clients, open files, or
|
||||
process handles. Layers declare a Pydantic `runtime_handles_type` with
|
||||
`arbitrary_types_allowed=True`. Handles are never serialized; resume hooks
|
||||
should rehydrate them from runtime state.
|
||||
|
||||
`Layer.__init_subclass__` infers `deps_type`, `config_type`,
|
||||
`runtime_state_type`, and `runtime_handles_type` from generic base arguments
|
||||
when possible. For example, `PlainLayer[NoLayerDeps, MyConfig, MyState,
|
||||
MyHandles]` automatically installs those Pydantic schemas. Omitted schema slots
|
||||
default to `EmptyLayerConfig`, `EmptyRuntimeState`, and `EmptyRuntimeHandles`.
|
||||
Lifecycle hooks can annotate controls as `LayerControl[MyState, MyHandles]` to
|
||||
get static checking and IDE completion for runtime state and handles.
|
||||
|
||||
## Registry and builder
|
||||
|
||||
Register config-constructible layers manually:
|
||||
|
||||
```python
|
||||
registry = LayerRegistry()
|
||||
registry.register_layer(PromptLayer) # uses PromptLayer.type_id == "plain.prompt"
|
||||
```
|
||||
|
||||
Use `CompositorBuilder` to mix serializable config nodes with live instances:
|
||||
|
||||
```python
|
||||
compositor = (
|
||||
CompositorBuilder(registry)
|
||||
.add_config(
|
||||
{
|
||||
"layers": [
|
||||
{
|
||||
"name": "prompt",
|
||||
"type": "plain.prompt",
|
||||
"config": {"prefix": "Hi", "user": "Answer with examples."},
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
.add_instance(name="profile", layer=ObjectLayer(profile))
|
||||
.build()
|
||||
)
|
||||
```
|
||||
|
||||
Use `.add_instance()` for layers that require Python objects or callables, such
|
||||
as `ObjectLayer`, `ToolsLayer`, and dynamic tool layers.
|
||||
|
||||
## System prompts and user prompts
|
||||
|
||||
Layers expose three prompt surfaces:
|
||||
|
||||
- `prefix_prompts`: system prompt fragments collected in layer order.
|
||||
- `suffix_prompts`: system prompt fragments collected in reverse layer order.
|
||||
- `user_prompts`: user-message fragments collected in layer order.
|
||||
|
||||
`PromptLayer` accepts `prefix`, `user`, and `suffix` config fields. For
|
||||
pydantic-ai, `PYDANTIC_AI_TRANSFORMERS` maps `compositor.prompts` to system
|
||||
prompt functions and `compositor.user_prompts` to values suitable for
|
||||
`Agent.run(user_prompt=...)`.
|
||||
|
||||
## Session snapshot and restore
|
||||
|
||||
`Compositor.snapshot_session(session)` serializes non-active sessions, including
|
||||
layer lifecycle state and runtime state. It rejects active sessions because live
|
||||
handles cannot be snapshotted safely. Restore with
|
||||
`Compositor.session_from_snapshot(snapshot)`; restored controls validate runtime
|
||||
state with each layer schema and initialize empty runtime handles. Suspended
|
||||
sessions resume through `on_context_resume`, where handles should be hydrated
|
||||
from the restored runtime state.
|
||||
|
||||
Create sessions with `Compositor.new_session()` or
|
||||
`Compositor.session_from_snapshot()`. `Compositor.enter()` validates that every
|
||||
session control uses the target layer's runtime state and handle schemas before
|
||||
any lifecycle hook runs.
|
||||
- [User guide](guide/) explains how to compose layers, register config-backed
|
||||
plugins, use system/user prompts, and snapshot sessions.
|
||||
- [API reference](api/) lists the public Agenton classes, methods, and extension
|
||||
points.
|
||||
|
||||
183
dify-agent/docs/agenton/api/README.md
Normal file
183
dify-agent/docs/agenton/api/README.md
Normal file
@@ -0,0 +1,183 @@
|
||||
# Agenton API reference
|
||||
|
||||
This page summarizes the public Agenton API. Import paths are shown for the
|
||||
symbols commonly used by layer authors and compositor callers.
|
||||
|
||||
## Layers: `agenton.layers`
|
||||
|
||||
### `Layer[DepsT, PromptT, UserPromptT, ToolT, ConfigT, RuntimeStateT, RuntimeHandlesT]`
|
||||
|
||||
Framework-neutral base class for prompt/tool layers.
|
||||
|
||||
Class attributes:
|
||||
|
||||
- `type_id: str | None`: registry id for config-backed plugin layers.
|
||||
- `config_type: type[BaseModel]`: Pydantic schema for serialized layer config.
|
||||
- `runtime_state_type: type[BaseModel]`: Pydantic schema for snapshot-safe
|
||||
per-session state.
|
||||
- `runtime_handles_type: type[BaseModel]`: Pydantic schema for live runtime
|
||||
handles; use `arbitrary_types_allowed=True` for client/process objects.
|
||||
- `deps_type: type[LayerDeps]`: inferred from the layer generic base or declared
|
||||
explicitly.
|
||||
|
||||
Construction and dependency APIs:
|
||||
|
||||
- `from_config(config: ConfigT) -> Self`: create a layer from schema-validated
|
||||
config. The default implementation raises `TypeError`.
|
||||
- `dependency_names() -> frozenset[str]`: dependency fields declared by
|
||||
`deps_type`.
|
||||
- `bind_deps(deps: Mapping[str, Layer | None]) -> None`: bind graph dependencies.
|
||||
- `new_control(state=LifecycleState.NEW, runtime_state=None) -> LayerControl`: create
|
||||
a schema-validated per-session control.
|
||||
|
||||
Lifecycle hooks:
|
||||
|
||||
- `on_context_create(control)`
|
||||
- `on_context_resume(control)`
|
||||
- `on_context_suspend(control)`
|
||||
- `on_context_delete(control)`
|
||||
- `enter(control)` / `lifecycle_enter(control)`: async context manager entry
|
||||
surface. Override `enter()` only when a layer needs to wrap extra resources.
|
||||
|
||||
Prompt/tool authoring surfaces:
|
||||
|
||||
- `prefix_prompts -> Sequence[PromptT]`
|
||||
- `suffix_prompts -> Sequence[PromptT]`
|
||||
- `user_prompts -> Sequence[UserPromptT]`
|
||||
- `tools -> Sequence[ToolT]`
|
||||
|
||||
Aggregation adapters implemented by typed layer families:
|
||||
|
||||
- `wrap_prompt(prompt: PromptT) -> object`
|
||||
- `wrap_user_prompt(prompt: UserPromptT) -> object`
|
||||
- `wrap_tool(tool: ToolT) -> object`
|
||||
|
||||
### `LayerControl[RuntimeStateT, RuntimeHandlesT]`
|
||||
|
||||
Per-layer, per-session lifecycle control.
|
||||
|
||||
Fields:
|
||||
|
||||
- `state: LifecycleState`
|
||||
- `exit_intent: ExitIntent`
|
||||
- `runtime_state: RuntimeStateT`
|
||||
- `runtime_handles: RuntimeHandlesT`
|
||||
|
||||
Methods:
|
||||
|
||||
- `suspend_on_exit() -> None`
|
||||
- `delete_on_exit() -> None`
|
||||
|
||||
`runtime_state` is serialized in session snapshots. `runtime_handles` is never
|
||||
serialized and should be rehydrated from runtime state in resume hooks.
|
||||
|
||||
### Schema defaults and lifecycle enums
|
||||
|
||||
- `EmptyLayerConfig`
|
||||
- `EmptyRuntimeState`
|
||||
- `EmptyRuntimeHandles`
|
||||
- `LifecycleState`: `NEW`, `ACTIVE`, `SUSPENDED`, `CLOSED`
|
||||
- `ExitIntent`: `DELETE`, `SUSPEND`
|
||||
|
||||
### Typed layer families: `agenton.layers.types`
|
||||
|
||||
- `PlainLayer[DepsT, ConfigT, RuntimeStateT, RuntimeHandlesT]`
|
||||
- `PydanticAILayer[DepsT, AgentDepsT, ConfigT, RuntimeStateT, RuntimeHandlesT]`
|
||||
|
||||
Tagged aggregate item types:
|
||||
|
||||
- `PlainPromptType`, `PlainUserPromptType`, `PlainToolType`
|
||||
- `PydanticAIPromptType`, `PydanticAIUserPromptType`, `PydanticAIToolType`
|
||||
- `AllPromptTypes`, `AllUserPromptTypes`, `AllToolTypes`
|
||||
|
||||
## Compositor: `agenton.compositor`
|
||||
|
||||
### Config models
|
||||
|
||||
- `LayerNodeConfig`: `name`, `type`, `config`, `deps`, `metadata`
|
||||
- `CompositorConfig`: `schema_version`, `layers`
|
||||
|
||||
Config nodes are pure serializable graph input. Use live instances for Python
|
||||
objects and callables.
|
||||
|
||||
### Registry
|
||||
|
||||
`LayerRegistry` manually registers config-backed layer classes.
|
||||
|
||||
- `register_layer(layer_type, type_id=None) -> None`
|
||||
- `resolve(type_id) -> LayerDescriptor`
|
||||
- `descriptors() -> Mapping[str, LayerDescriptor]`
|
||||
|
||||
`LayerDescriptor` exposes `type_id`, `layer_type`, `config_type`,
|
||||
`runtime_state_type`, and `runtime_handles_type`.
|
||||
|
||||
### Builder
|
||||
|
||||
`CompositorBuilder(registry)` mixes config-backed nodes and live instances.
|
||||
|
||||
- `add_config(config) -> Self`
|
||||
- `add_config_layer(name, type, config=None, deps=None) -> Self`
|
||||
- `add_instance(name, layer, deps=None) -> Self`
|
||||
- `build(prompt_transformer=None, user_prompt_transformer=None, tool_transformer=None) -> Compositor`
|
||||
|
||||
### Compositor
|
||||
|
||||
`Compositor[PromptT, ToolT, LayerPromptT, LayerToolT, UserPromptT, LayerUserPromptT]`
|
||||
owns the ordered layer graph.
|
||||
|
||||
Construction:
|
||||
|
||||
- `Compositor(layers=..., deps_name_mapping=..., ...)`
|
||||
- `Compositor.from_config(conf, registry=..., ...)`
|
||||
|
||||
Aggregation properties:
|
||||
|
||||
- `prompts -> list[PromptT]`: prefix prompts in layer order, suffix prompts in
|
||||
reverse layer order, then optional `prompt_transformer`.
|
||||
- `user_prompts -> list[UserPromptT]`: user prompts in layer order, then optional
|
||||
`user_prompt_transformer`.
|
||||
- `tools -> list[ToolT]`: tools in layer order, then optional `tool_transformer`.
|
||||
|
||||
Session APIs:
|
||||
|
||||
- `new_session() -> CompositorSession`
|
||||
- `enter(session=None) -> AsyncIterator[CompositorSession]`
|
||||
- `snapshot_session(session) -> CompositorSessionSnapshot`
|
||||
- `session_from_snapshot(snapshot) -> CompositorSession`
|
||||
|
||||
### Sessions and snapshots
|
||||
|
||||
`CompositorSession` owns ordered layer controls.
|
||||
|
||||
- `suspend_on_exit() -> None`
|
||||
- `delete_on_exit() -> None`
|
||||
- `layer(name) -> LayerControl`
|
||||
|
||||
Snapshot models:
|
||||
|
||||
- `LayerSessionSnapshot`: `name`, `state`, `runtime_state`
|
||||
- `CompositorSessionSnapshot`: `schema_version`, `layers`
|
||||
|
||||
Snapshots reject active sessions and exclude `runtime_handles` and `exit_intent`.
|
||||
|
||||
## Collection layers and transformers
|
||||
|
||||
### Plain layers: `agenton_collections.layers.plain`
|
||||
|
||||
- `PromptLayer`: config-backed layer with `PromptLayerConfig(prefix, user,
|
||||
suffix)` and `type_id = "plain.prompt"`.
|
||||
- `ObjectLayer`: instance-only layer for Python objects.
|
||||
- `ToolsLayer`: instance-only layer for callables.
|
||||
- `DynamicToolsLayer`: instance-only layer for object-bound callables.
|
||||
|
||||
### Pydantic AI bridge
|
||||
|
||||
`agenton_collections.layers.pydantic_ai.PydanticAIBridgeLayer` exposes
|
||||
pydantic-ai system prompts, user prompts, and tools while depending on an
|
||||
`ObjectLayer` for `RunContext.deps`.
|
||||
|
||||
`agenton_collections.transformers.PYDANTIC_AI_TRANSFORMERS` provides:
|
||||
|
||||
- `prompt_transformer`: maps `compositor.prompts` to pydantic-ai system prompt functions.
|
||||
- `user_prompt_transformer`: maps `compositor.user_prompts` to pydantic-ai `UserContent`.
|
||||
- `tool_transformer`: maps `compositor.tools` to pydantic-ai tools.
|
||||
117
dify-agent/docs/agenton/guide/README.md
Normal file
117
dify-agent/docs/agenton/guide/README.md
Normal file
@@ -0,0 +1,117 @@
|
||||
# Agenton user guide
|
||||
|
||||
Agenton composes shared `Layer` instances into a named graph. Treat layer
|
||||
instances as reusable capability definitions: config and dependency declarations
|
||||
belong on the layer class or instance, while per-session runtime values belong
|
||||
on the `LayerControl` created for that layer in a `CompositorSession`.
|
||||
|
||||
## Config, runtime state, and runtime handles
|
||||
|
||||
- **Config** is serializable graph input. Config-constructible layers declare a
|
||||
`type_id` and a Pydantic `config_type`; builders validate node config before
|
||||
calling `Layer.from_config(validated_config)`.
|
||||
- **Runtime state** is serializable per-layer/per-session state. Layers declare a
|
||||
Pydantic `runtime_state_type`; session snapshots persist this model with
|
||||
`model_dump(mode="json")`.
|
||||
- **Runtime handles** are live Python objects such as clients, open files, or
|
||||
process handles. Layers declare a Pydantic `runtime_handles_type` with
|
||||
`arbitrary_types_allowed=True`. Handles are never serialized; resume hooks
|
||||
should rehydrate them from runtime state.
|
||||
|
||||
## Define a config-backed layer
|
||||
|
||||
Use a Pydantic model for config and pass it through the typed layer family so
|
||||
`Layer.__init_subclass__` can infer the schema:
|
||||
|
||||
```python
|
||||
class GreetingConfig(BaseModel):
|
||||
prefix: str
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
|
||||
@dataclass
|
||||
class GreetingLayer(PlainLayer[NoLayerDeps, GreetingConfig]):
|
||||
type_id = "example.greeting"
|
||||
prefix: str
|
||||
|
||||
@classmethod
|
||||
def from_config(cls, config: GreetingConfig) -> Self:
|
||||
return cls(prefix=config.prefix)
|
||||
|
||||
@property
|
||||
def prefix_prompts(self) -> list[str]:
|
||||
return [self.prefix]
|
||||
```
|
||||
|
||||
Omitted schema slots default to `EmptyLayerConfig`, `EmptyRuntimeState`, and
|
||||
`EmptyRuntimeHandles`. Lifecycle hooks can annotate controls as
|
||||
`LayerControl[MyState, MyHandles]` to get static checking and IDE completion for
|
||||
runtime state and handles.
|
||||
|
||||
## Register layers and build a compositor
|
||||
|
||||
Register config-constructible layers manually:
|
||||
|
||||
```python
|
||||
registry = LayerRegistry()
|
||||
registry.register_layer(PromptLayer) # uses PromptLayer.type_id == "plain.prompt"
|
||||
```
|
||||
|
||||
Use `CompositorBuilder` to mix serializable config nodes with live instances:
|
||||
|
||||
```python
|
||||
compositor = (
|
||||
CompositorBuilder(registry)
|
||||
.add_config(
|
||||
{
|
||||
"layers": [
|
||||
{
|
||||
"name": "prompt",
|
||||
"type": "plain.prompt",
|
||||
"config": {"prefix": "Hi", "user": "Answer with examples."},
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
.add_instance(name="profile", layer=ObjectLayer(profile))
|
||||
.build()
|
||||
)
|
||||
```
|
||||
|
||||
Use `.add_instance()` for layers that require Python objects or callables, such
|
||||
as `ObjectLayer`, `ToolsLayer`, and dynamic tool layers.
|
||||
|
||||
## System prompts and user prompts
|
||||
|
||||
Layers expose three prompt surfaces:
|
||||
|
||||
- `prefix_prompts`: system prompt fragments collected in layer order.
|
||||
- `suffix_prompts`: system prompt fragments collected in reverse layer order.
|
||||
- `user_prompts`: user-message fragments collected in layer order.
|
||||
|
||||
`PromptLayer` accepts `prefix`, `user`, and `suffix` config fields. For
|
||||
pydantic-ai, `PYDANTIC_AI_TRANSFORMERS` maps `compositor.prompts` to system
|
||||
prompt functions and `compositor.user_prompts` to values suitable for
|
||||
`Agent.run(user_prompt=...)`.
|
||||
|
||||
## Session snapshot and restore
|
||||
|
||||
`Compositor.snapshot_session(session)` serializes non-active sessions, including
|
||||
layer lifecycle state and runtime state. It rejects active sessions because live
|
||||
handles cannot be snapshotted safely. Restore with
|
||||
`Compositor.session_from_snapshot(snapshot)`; restored controls validate runtime
|
||||
state with each layer schema and initialize empty runtime handles. Suspended
|
||||
sessions resume through `on_context_resume`, where handles should be hydrated
|
||||
from the restored runtime state.
|
||||
|
||||
Create sessions with `Compositor.new_session()` or
|
||||
`Compositor.session_from_snapshot()`. `Compositor.enter()` validates that every
|
||||
session control uses the target layer's runtime state and handle schemas before
|
||||
any lifecycle hook runs.
|
||||
|
||||
See also:
|
||||
|
||||
- `examples/agenton/basics.py`
|
||||
- `examples/agenton/pydantic_ai_bridge.py`
|
||||
- `examples/agenton/session_snapshot.py`
|
||||
Reference in New Issue
Block a user