That's it, in the corner.
It's the real assistant that runs this site. Click it and ask anything about AgentGraft.
It reads the room.
The face carries the whole state of the widget, so the button never needs a label. It notices the page and the person on it: when you come close, when it's busy writing, when everything has gone quiet, and how the one typing feels.
01 What it's doing.
Six states, straight from the widget. Its eyes move in saccades, snap and hold, and it blinks at uneven intervals, so it never looks like a loop.
02 How it feels.
Sixteen expressions, from delight to grief and calm to alarm, plus the looks a conversation runs on: a wink, a raised brow, a slow nod while someone vents. As a visitor types, a fast classifier reads each message and the face answers while the words are still arriving.
It responds rather than mirrors. Panic gets focus, bad news gets sympathy, a compliment gets a blush. Every expression is a pose, not a clip, so it moves between any two without a seam.
Attentive
Drag on the circle to blend any of them.
It remembers who it's talking to.
Set memory_enabled=True and that's the setup.
When a conversation gets long, a background agent sleeps on it and keeps what's worth keeping as facts in a small graph, like "Maya manages the Lisbon team".
It updates facts that change and retires the ones that stop being true.
People can say "remember that" or "forget that" mid-chat, and see, edit or delete every fact from the widget's settings. A fact they edit is theirs; the agent won't touch it again.
mardi
Pull signups by week. ISO weeks please, we report Monday to Sunday.
Here are weeks 36 to 39, Monday start: Signups by week
Kept: reports in ISO weeks, Monday start.
The next Tuesday
Same report as last week?
Weeks 37 to 40, ISO weeks like last time, as a CSV: Signups by week
What it knows about Maya
From the widget's settings- Reports in ISO weeks, Monday start
- Manages the Lisbon team
- Prefers CSV exports to charts
Ship it with one command.
agentgraft_sync reads the file, resolves your policies from the Policy Shop, and pushes tools, agents and settings as one atomic update.
Either every change lands or none does.
Put it in your pre-deploy step and the assistant ships with the code that serves it.
A prompt change is a diff your team reviews in a pull request, and git revert rolls it back.
~/ledgerline
pre-deploy
The next message uses the new config.
One tag for the web. Python for everything else.
Put the tag in your base template for an assistant on every page, or in one template to scope it. It signs the visitor's identity on your server, so AgentGraft knows who is asking without touching your database.
Not every conversation happens in a browser.
ag.Client brings the same tools and the same memory of each person to a Slack bot, a WhatsApp number or your mobile app.
- Web widget
- Slack
- Mobile
- Your own UI
templates/base.html{% load agentgraft %} {% agentgraft_widget %}
slack_bot.py
headless
import agentgraft as ag client = ag.Client.from_profile("default") # In your Slack handler. Same person, same memory. response = client.chat( user_id=f"slack:{event['user']}", message=event["text"], auto_route=True, ) say(response["text"])
Your data never leaves your app.
AgentGraft holds the conversation and the shape of your tools. Your app holds the users, the data and the code. When the assistant needs a tool, AgentGraft sends a signed request to your webhook; your function runs where your data already lives and returns only what you wrote it to return.
Visitor's browser
- The widget
- An identity your server signed
messages and streamed replies
HMAC-SHA256 signed identity
AgentGraft
- Tool schemas, never tool code
- Conversations
- Memory, encrypted per visitor
tool calls over signed webhooks, replay-protected
POST /agentgraft/webhook/
Your Django app
- Utilisateurs
- Data
- Tool code, and every tool run
Delete a visitor and they're gone. Backups too.
Every visitor gets their own AES-256-GCM key, chained to your app's secret by a23crypt. Delete the visitor and the key goes with them: every copy of what they said, backups and replicas included, becomes unreadable noise.
Visitors can export everything as JSON and edit or delete any remembered fact. The ghost button opens a private chat that leaves nothing behind.
Maya Ortizuser:4127
- 1Prefers growth month over month, not week over week.
- 2Sends growth numbers to finance on Mondays.
- 3Maya —manages→ the Lisbon team.
- 4Owns the Q3 revenue dataset.
4 facts kept from 3 conversations.
Also in the file.
Each of these is one line in agentgraft_config.py, or already in the widget.
- Accent colour
- palette="jade"
- Buttons, links and the face take your colour, in light and dark. Visitors can pick their own if you let them.
- Diagrams and math
- in the widget
- Mermaid diagrams, KaTeX math and highlighted code blocks render inside replies.
- Follow-up questions
- followups_enabled=True
- Each reply ends with a few questions the visitor might ask next.
- Handoffs
- handoffs=["billing"]
-
One agent passes the conversation to another.
sub_agentsdelegates a task and takes the answer back. - Image attachments
- image_uploads_enabled=True
- Visitors drop, paste or pick images to ask about.
- Long-term memory
- memory_enabled=True
- A background agent sleeps on each conversation and curates facts into a graph. A recall agent finds them when they matter.
- Policy Shop
- ag.policy("agentgraft/cite-sources")
- Reusable prompt fragments, referenced by codename and resolved at sync.
- Private chat
- @ag.agent(private=True)
- A ghost button for an incognito chat that stores nothing.
- Recap
- recap_enabled=True
- When a visitor comes back to an idle thread, a short note on where they left off is waiting.
- References
- ag.ref("dataset", id, name)
- Objects your tools return become chips that link straight into your app.
- Voice
- voice_enabled=True
- Visitors talk instead of type, and hear replies read aloud.