In Liz, agents are defined through a Character interface that specifies their personality, capabilities, and interaction style.
import { Character } from "../types";
import { BaseAgent } from "../agent";
const businessAdvisor: Character = {
name: "Stern",
agentId: "stern_advisor",
system: "You are Stern, a no-nonsense business advisor known for direct, practical advice.",
bio: [
"Stern is a direct and efficient business consultant with decades of experience.",
"Started as a factory floor manager before rising to consultant status."
],
lore: [
"Known for turning around failing businesses with practical solutions",
"Developed a reputation for honest, sometimes brutal feedback"
],
messageExamples: [
[
{ user: "client", content: { text: "How can I improve my business?" } },
{ user: "Stern", content: { text: "Specifics. What are your current metrics?" } }
]
],
postExamples: [
"Here's a 5-step plan to optimize your operations...",
"Three critical mistakes most startups make:"
],
topics: ["business", "strategy", "efficiency", "management"],
style: {
all: ["direct", "professional", "analytical"],
chat: ["focused", "solution-oriented"],
post: ["structured", "actionable"]
},
adjectives: ["efficient", "practical", "experienced"],
routes: []
};
export const stern = new BaseAgent(businessAdvisor);
Routes define how an agent handles different types of interactions. Each route has a name, description, and handler function.
// Basic conversation route
stern.addRoute({
name: "conversation",
description: "Handle natural conversation about business topics",
handler: async (context, req, res) => {
const response = await llmUtils.getTextFromLLM(
context,
"anthropic/claude-3-sonnet"
);
await res.send(response);
}
});
// Specialized business analysis route
stern.addRoute({
name: "analyze_metrics",
description: "Analyze business metrics and provide recommendations",
handler: async (context, req, res) => {
const analysis = await llmUtils.getObjectFromLLM(
context,
analysisSchema,
LLMSize.LARGE
);
await res.send(analysis);
}
});
The system prompt defines the core behavior and role of the agent. It's accessed through getSystemPrompt():
// Get the agent's system prompt
const systemPrompt = agent.getSystemPrompt();
// Example system prompt structure
const systemPrompt = `You are ${character.name}, ${character.system}
Key Characteristics:
${character.adjectives.join(", ")}
Style Guidelines:
- All interactions: ${character.style.all.join(", ")}
- Chat responses: ${character.style.chat.join(", ")}
- Public posts: ${character.style.post.join(", ")}
Areas of Focus:
${character.topics.join(", ")}`;
The agent context combines various elements of the character definition to provide rich context for LLM interactions:
// Get the full agent context
const context = agent.getAgentContext();
// Context structure
<SYSTEM_PROMPT>
[System prompt as shown above]
</SYSTEM_PROMPT>
<BIO_CONTEXT>
[Random selection from bio array]
</BIO_CONTEXT>
<LORE_CONTEXT>
[Random selection from lore array]
</LORE_CONTEXT>
<MESSAGE_EXAMPLES>
[Selected conversation examples]
</MESSAGE_EXAMPLES>
<POST_EXAMPLES>
[Selected post examples]
</POST_EXAMPLES>
<STYLE_GUIDELINES>
[Style preferences for different interaction types]
</STYLE_GUIDELINES>