Reasoning
Agents can handle complex conversations by managing multiple steps in sequence, maintaining context, and waiting for user responses. This creates a more natural interaction flow.
Overview
For full reasoning we need to combine the following skills:
- Scenarios: Train your agent for reliable responses.
- Prompting: System prompt to teach available skills to the agent.
- Processing: Handle multiple skills in a single conversation.
- Parsing: Interpret user intent and translate it into a defined skill.
- Definition: Define skills, parameters and handlers.
Example: Ens domain registration
Now let's put all these powerfull pieces together to create a more complex interaction.
Let's walk through a complete ENS domain registration flow:
User initiates the conversation
let's register humanagent.eth
Agent creates a response
The agent processes the natural language input "let's register fabriethsf.eth" and breaks it down into sequential steps:
[
"Hello! I'll help you get your domain.",
"Let's start by checking your ENS domain. Give me a moment.",
"/check humanagent.eth",
]
Skills
These are some of the skills the agent can use with its definition and handler implementation:
import { ensUrl } from "../index.js";
import { XMTPContext, getUserInfo } from "@xmtp/message-kit";
import type { skillAction } from "@xmtp/message-kit";
export const registerSkill: skillAction[] = [
{
skill: "/check [domain]",
handler: handleCheck,
examples: ["/check vitalik.eth", "/check fabri.base.eth"],
description: "Check if a domain is available.",
params: {
domain: {
type: "string",
},
},
},
];
export async function handleCheck(context: XMTPContext) {
const {
message: {
content: {
params: { domain },
},
},
} = context;
const data = await getUserInfo(domain);
if (!data?.address) {
let message = `Looks like ${domain} is available! Here you can register it: ${ensUrl}${domain} or would you like to see some cool alternatives?`;
return {
code: 200,
message,
};
} else {
let message = `Looks like ${domain} is already registered!`;
await context.executeSkill("/cool " + domain);
return {
code: 404,
message,
};
}
}
Skills declaration
The agent processes the natural language input "let's register fabriethsf.eth" and breaks it down into sequential steps:
export const skills = [
{
name: "Ens Domain Bot",
tag: "@ens",
description: "Register ENS domains.",
skills: [
...checkSkill,
...coolSkill,
...infoSkill,
...registerSkill,
...renewSkill,
...resetSkill,
...tipSkill,
],
},
];
Return a resposonse
The agent returns a response to the user:
run(
async (context: XMTPContext) => {
const {
message: { sender },
skills,
} = context;
let prompt = await replaceVariables(
systemPrompt,
sender.address,
skills,
"@ens",
);
fs.writeFileSync("example_prompt.md", prompt);
await agentReply(context, prompt);
},
{ skills },
);
This is a very simple example, but it shows how the agent can handle complex interactions by managing multiple steps in sequence, maintaining context, and waiting for user responses.