$ai
$ai runs an agent inside a _Space.
The space's folder is the agent's workspace, and the files under
.ai/ in it are the agent: its prompt and model, its tools and its
skills. There is nothing to register: an app writes files, then calls the agent.
The docs talk to a stub model, so every turn is predictable: plain text comes back as
echo: …, and a line like
!tool my_books {} makes the model call a tool. A session belongs
to whoever is asking, so if you are not signed in your first message makes you a guest account.
Talk to the agent
// In a browser handler (or a server controller, or a service):
const agent = $ai.agent('demo-chat', { space, agent: 'assistant' })
const off = agent.on('event', (event) => this.events.push(event))
const result = await agent.say(this.message) // { turn, text, ... }
off()
this.reply = result.text
The agent is its files
Your first message builds this workspace with ordinary $data and
$file calls. A tool runs as the person in the session, so
my_books lists the books you may read: the seeded ones
and your own. Access to the space is access to the agent; there is no second permission system.
// The workspace: a _Space whose root folder holds the agent's files.
workspace/
.ai/agents/assistant.json the agent
.ai/tools/my_books.js a tool
.ai/skills/next-read/SKILL.md a skill
notes.md a file its read_file tool can see
// .ai/agents/assistant.json
{
"prompt": "You are the C&C docs assistant. Answer briefly.",
"model": {
"provider": "llama.cpp",
"id": "stub/script"
},
"tools": [
"my_books"
],
"skills": [
"next-read"
]
}
// .ai/tools/my_books.js
// A tool runs as the person talking to the agent, so $data here
// sees exactly the books they may read: the seeded ones and their own.
export default {
description: 'List the books the person talking to the agent may read',
parameters: { type: 'object', properties: {} },
async run() {
const { rows } = await $data({
_schema: 'DataBook',
_select: ['title', 'author'],
_order: [{ field: 'title', direction: 'asc' }],
})
return rows.map((book) => book.title + ' by ' + book.author)
},
}
The session remembers
agent.history() is the conversation as the platform keeps it,
durable across reloads. Reload this page and the session picks up where it left off.