Prompt Management
Languages: English · 中文
Agently splits a prompt into named slots. The slots compose, so you can set persistent agent context once and only fill request-specific slots per call.
Slot map
| Slot | Where it ends up | Typical use |
|---|---|---|
role / system | system message | persona, capability boundaries |
info | system or user (impl detail) | background facts, inventories, tool catalogs |
instruct | user message | step-by-step instructions for this kind of request |
input | user message | the actual question or payload |
output | user message + parser | the schema you want back |
Setting a slot persistently:
agent = (
Agently.create_agent()
.role("You are an Agently support assistant.", always=True)
.info({"product": "Agently 4.x"}, always=True)
)always=True keeps the slot at the agent level so it carries to every request the agent runs.
Setting a slot for one request:
result = (
agent
.instruct(["Reply in fewer than 80 words.", "Never invent product names."])
.input("How do I configure a model?")
.output({"answer": (str, "answer", True)})
.start()
)instruct(...) here is per-request because always=True was not passed.
Agent vs execution scope
| Scope | API |
|---|---|
| Agent definition (persists for every future execution) | .define(...), .role(..., always=True), .info(..., always=True), .set_agent_prompt(key, value) |
| AgentExecution draft (one execution only) | .input(...), .output(...), .set_execution_prompt(key, value) |
The slot you set last wins for that scope, so you can override agent defaults in one execution without mutating the agent. set_turn_prompt(...) and set_request_prompt(...) remain compatibility aliases for execution-local prompt writes.
YAML / JSON prompt files
Same slot model, written declaratively:
# prompts/triage.yaml
$ensure_all_keys: true
.agent:
system: You are a ticket triage assistant.
info:
severities: ["P0", "P1", "P2", "P3"]
.execution:
instruct: Classify the ticket text.
output:
$format: json
severity:
$type: str
$desc: One of P0/P1/P2/P3
$ensure: true
rationale:
$type: str
$desc: One-line reason
$ensure: trueLoading:
agent = Agently.create_agent().load_yaml_prompt("prompts/triage.yaml")
result = (
agent
.create_execution()
.set_execution_prompt("input", "Login fails for all users in EU region.")
.start()
)load_json_prompt(...) is the same API for JSON. Both accept either a path or a raw string body. Pick one config file per prompt or stack multiple prompts with prompt_key_path="demo.output_control" to select inside a multi-prompt file.
Prompt config uses .execution for one execution. .turn and .request remain compatibility aliases for older prompt files.
$ensure_all_keys: true at the top makes all leaves required regardless of per-leaf $ensure. Use it when the entire schema must come back complete.
$format on the output block maps to the same output format setting as .output(..., format=...). Supported values are auto, json, flat_markdown, hybrid, xml_field, and yaml_literal. You can also use .format, $output_format, or .output_format when a config file needs a more explicit key.
Round-tripping
You can convert a Python-built prompt back to YAML/JSON for review or storage:
agent.role("You are an Agently agent.", always=True).input("Say hello.").output({
"reply": (str, "reply", True),
})
print(agent.get_yaml_prompt())
print(agent.get_json_prompt())
print(agent.get_prompt_text()) # the rendered text the model will seeThis round-trip is the canonical way to compare "what I think I'm sending" against "what the framework actually sends".
Placeholders
Inside any prompt slot, {name} references another slot by key, and ${name} is replaced by mappings={"name": "value"} at load time. Common patterns:
instruct: "Reply {input} politely."— pulls the requestinputinto the instruct text.${ENV.OPENAI_API_KEY}in settings (not prompts) is replaced by the env var; prompts use${name}with explicit mappings.${INPUT.customer},${INFO.policy}, and${INSTRUCT.step}are render-time slot references. They become prompt section pointers such as[INPUT > customer]instead of copying slot values into another slot. Slot names are case-insensitive; docs use uppercase. The path after the slot name is not validated because it is only a model-facing reference label.${OUTPUT}is an alias for[OUTPUT REQUIREMENT].
To trigger placeholder substitution while loading, pass mappings=... explicitly:
agent.load_yaml_prompt(yaml_text, mappings={"product_name": "Agently"})Where each layer's prompt comes from
When a request runs, Agently composes the final prompt by stacking:
- Agent-level slots (set with
always=Trueorset_agent_prompt) - Request-level slots (set without
always=True) - Slots populated by framework extensions or application code (Session injects chat history; retrieval code usually puts snippets into per-request
info(...))
Use agent.get_prompt_text() to see the merged result before sending.
See also
- Schema as Prompt — leaf authoring,
$ensure - Output Control — what happens after parsing
- Project Framework — file layout for managing many prompts