Agently documentation for building AI applications with stable outputs, observable actions, and durable workflows.
Languages: English · 中文
A user controls something — a document, a dashboard, a set of records — by typing natural-language commands. Each turn, the model:
User input → Agent (with actions) → action call(s) → updated state → reply
▲
│
Session (multi-turn history)
This is fundamentally a conversational agent with actions. No TriggerFlow needed unless you have multi-step processes per turn.
from agently import Agently
agent = (
Agently.create_agent()
.role("You control a shopping cart. Use the available actions to make changes.", always=True)
.info({"format": "After each action, briefly confirm what changed."}, always=True)
)
# A simple in-memory cart for the demo
cart = {"items": [], "total": 0.0}
@agent.action_func
def add_item(name: str, price: float, quantity: int = 1):
"""Add a product to the cart."""
cart["items"].append({"name": name, "price": price, "quantity": quantity})
cart["total"] += price * quantity
return cart
@agent.action_func
def remove_item(name: str):
"""Remove a product from the cart."""
cart["items"] = [i for i in cart["items"] if i["name"] != name]
cart["total"] = sum(i["price"] * i["quantity"] for i in cart["items"])
return cart
@agent.action_func
def show_cart():
"""Return the current cart state."""
return cart
agent.use_actions([add_item, remove_item, show_cart])
# Enable a session so multi-turn context is bounded
agent.activate_session(session_id="cart-demo")
# Conversation loop
while True:
user_text = input("> ")
if not user_text.strip():
break
reply = agent.input(user_text).start()
print(reply)
@agent.action_func for each operation, not a single “do anything” tool — small, well-named actions let the model pick correctly. A monolithic tool forces the model to encode parameters in JSON inside a string.role(always=True) for behavior, info(always=True) for formatting — both are stored on the agent and included in every request that agent runs, so they count toward each request’s prompt.activate_session() instead of manual chat history management — for chat-style interactions, Session maintains full history and the current context window. Register a custom resize handler when you need summarization. See Session Memory.For a UI, switch to streaming so the user sees the response as it’s generated:
gen = agent.input(user_text).get_generator(type="delta")
for delta in gen:
print(delta, end="", flush=True)
See Model Response for streaming options.
If your UI needs to know which action ran (to highlight a row, animate, etc.), read agent.get_action_result() after each turn:
records = agent.get_action_result()
for r in records:
notify_ui(action=r.name, args=r.input, result=r.output)
If a single user message triggers a multi-step process (lookup → confirm → apply), promote the per-turn handling to a TriggerFlow. The conversation layer still lives in the agent; the flow runs inside one turn. See TriggerFlow Orchestration Playbook.
@agent.action_func and use_actionsactivate_session(), windowing, custom memo