Prompts, Responses and Beliefs
Most LLM calls combine fixed instructions with values that change from call to call, and most replies contain a value the agent needs to extract. The Templater module handles both. This page also shows how to include the agent’s beliefs in a prompt.
Create and reuse prompts
Templater creates PromptTemplate objects. A placeholder such as ${topic} is bound with addBinding(...); all placeholders must be bound before a template can be sent through chat(...). Use reset(...) before reusing a template with a new set of bindings.
For a small demonstration that requires no credentials or network access, save this file as src/main/astra/LLMTemplatesDemo.astra:
Download LLMTemplatesDemo.astra
import astra.langchain4j.*;
agent LLMTemplatesDemo {
module Templater tpl;
module Console C;
module System S;
types food {
formula food(string);
}
initial food("apple"), food("carrot");
plan +!main(list args) {
PromptTemplate prompt = tpl.createPromptTemplate("Classify ${item}.");
tpl.addBinding(prompt, "item", "apple");
C.println(tpl.toString(prompt));
ResponseTemplate response = tpl.createResponseTemplate("RESULT[${answer}]");
tpl.inferBindings(response, "RESULT[fruit]");
string Answer = tpl.getBinding(response, "answer");
C.println("answer=" + Answer);
// Build context from the current beliefs without making an LLM call.
string Context = "Which of these foods are fruits?";
foreach (food(string Item)) {
Context = Context + " Food: " + Item + ".";
}
C.println(Context);
S.exit();
}
}
Run it with:
mvn -Dastra.main=LLMTemplatesDemo
The output begins with:
[main] Classify apple.
[main] answer=fruit
It then prints a prompt containing the two food beliefs. Their enumeration order is not part of the example’s contract.
Extract and validate responses
A ResponseTemplate describes the text around values that should be extracted. The example above matches RESULT[fruit] against RESULT[${answer}] and reads the resulting binding. Text before the first literal is ignored, and a placeholder at the end of a template takes the rest of the reply.
For a live request, ask the model to use the same format, then call inferBindings(...) and getBinding(...) on the returned text. The reasoning agents use this technique throughout: their prompts ask the model to enclose its answer in <answer></answer> tags, and they extract it with the template <answer>${answer}</answer>.
Treat this as text extraction, not a guarantee that the answer is correct. Check extracted values against the expected domain before using them in actions. For example, a move for Tic-Tac-Toe must be in range and target an empty cell. When a reply does not match the template, inferBindings(...) fails; handle that with try/recover and a retry or fallback plan.
Each chat(...) call receives only the text supplied for that call. If an application needs conversation history, carry that history explicitly in beliefs, lists or a template rather than assuming earlier calls are remembered. The ReAct agent, for example, rebuilds its history into every prompt.
Include beliefs in a prompt
The foreach loop in LLMTemplatesDemo is the simplest way to turn beliefs into prompt text: query the beliefs that are relevant to the question and append a sentence for each. Select only what the question needs rather than including the whole belief base.
The resulting Context string can be passed to llm.chat(Context, string Reply) after model initialization.
BeliefRAG is a reusable form of the same idea. The library exposes it through the BelRAG module and RAGTemplate:
module BelRAG rag;
Inside a plan, the mapping is expressed as:
RAGTemplate facts = rag.createRAGTemplate("Which of these foods are fruits?");
rag.addInput(facts, food(string Item), "Food: ${Item}.");
Each input associates a query with a sentence template. The beliefs are retrieved when the prompt is rendered, so a reusable template can reflect changes in the agent’s state. It does not require a vector database.
Note
In ASTRA 2.3.0, RAGInput still has a binding defect: its binding method returns false, so query results can leave placeholders unresolved. Use a foreach loop, as in LLMTemplatesDemo, to construct context from beliefs until that defect is corrected.
Combine templates
A CompositeTemplate joins multiple templates into one prompt. This is useful for combining instructions, task details and current state:
CompositeTemplate combined = tpl.createCompositeTemplate();
PromptTemplate instructions = tpl.createPromptTemplate("Answer briefly.");
PromptTemplate task = tpl.createPromptTemplate("Explain ${topic}.");
tpl.addBinding(task, "topic", "agent beliefs");
tpl.addTemplate(combined, instructions);
tpl.addTemplate(combined, task);
llm.chat(combined, string Reply);
This fragment belongs inside an initialized agent’s plan. The library also permits RAG templates in a composite, subject to the binding limitation described above.
Where next?
The reasoning architecture packages these techniques into reusable prompting strategies.