AgentGraft

Get started

Concepts

The seven words you need to navigate the rest of these docs without flinching.

4 min read

AgentGraft has a small vocabulary. Read this page once and the rest of the docs will make sense without you having to keep a glossary open. Every term here corresponds to either a database row, a decorator, or both — there are no abstract concepts you can't grep for.

#The mental model in one sentence

A Workspace owns one or more Grafts; each Graft is a single chat-widget integration; each Graft has its own Tools, Agents, and prompt content; the host app declares all of that in code via a named Profile and pushes it with one sync command.

#Workspace

Workspace
The paying entity. Owns grafts, members, and billing. Created automatically at signup as your personal workspace, with you as the OWNER. You can create more workspaces from the dashboard at any time, and add members with roles (OWNER, ADMIN, DEVELOPER, VIEWER).

Workspaces are the multi-tenant boundary. A user with a membership in workspace A cannot see grafts, conversations, or members of workspace B unless they're also a member there. Switching workspaces in the dashboard is a navigation action, not a login — your identity stays the same, only the scope changes.

#Graft

Graft
One chat-widget integration. Has its own credentials triple (api_key, public_key, webhook_secret), its own webhook URL, its own tools and agents, and its own conversation history. A workspace can own as many grafts as you want — one for your marketing site, another for your in-app helper, a third for an admin-only assistant — and they share nothing at the row level.

The metaphor is botanical. A graft is grown on a host (your Django app) and bears its fruit (the chat experience) on that host's surface. The hosted runtime provides the scaffolding but the integration belongs to your codebase.

#Profile

Profile
A name in the host app's AGENTGRAFT['profiles'] settings dict that maps to one graft's credentials. Profile names are arbitrary strings — default, marketing, admin. Every decorator (@ag.tool, @ag.agent) takes an optional profile= keyword that pins it to a specific profile's registry.

If your host app only has one chat experience, the default profile is the only one you need. Multi-profile setups become useful when you have, say, a marketing chat for anonymous visitors AND an in-app helper for authenticated users — same Python file, two completely separated tool registries, two separated grafts on the server.

#Tool

Tool
A Python function the LLM can call. Decorated with @ag.tool. Takes the resolved user object as its first argument; type hints on subsequent arguments are auto-converted to a JSON schema the LLM consumes. The function runs inside your host app's process — AgentGraft's runtime hits your webhook, the SDK dispatches to the matching function, the return value is JSON-serialised back to the LLM.
python
@ag.tool
def get_dataset(user: User, dataset_id: int) -> dict:
    """Get one dataset's metadata by id."""
    ds = Dataset.objects.get(pk=dataset_id, owner=user)
    return {"id": ds.id, "name": ds.name, "rows": ds.row_count}
The user argument is automatically resolved by your @ag.user_loader.

#Agent

Agent
A named persona with an instruction prompt, a list of tools it can call, and an optional list of agents it can hand off to. Decorated with @ag.agent. One agent per graft must be the entry point — that's the agent the orchestrator hands every new conversation to. Optionally, one other agent is private: it answers the widget's incognito chat, which is not saved.

Agents are how you compose complex chat experiences without writing one giant system prompt. A typical setup has a small router agent that triages incoming messages, plus a handful of specialist agents (one for billing questions, one for data lookups, one for documentation search) that the router hands off to as needed.

#Policy

Policy
A reusable piece of system-prompt text that ships in the AgentGraft Policy Shop. Reference one with ag.policy("agentgraft/no-hallucination") and the sync command fetches the body from the Policy Shop and substitutes it into your graft's prompt at sync time. Policies cover common needs like 'never invent values', 'cite sources', 'use markdown for emphasis', 'redact secrets'.

Policies are an optional convenience — you can write any text directly into the policies=[...] list on your graft. The Policy Shop just saves you from copy-pasting the same five rules into every project.

#User identity

User loader
A function the SDK calls to resolve an external user id (an opaque string the host app chose) back to a real user object. Decorated with @ag.user_loader. Whatever you return becomes the first argument to every tool function in that profile.

AgentGraft never stores your users — it just passes their external ids around. The widget signs the user id with the graft's webhook secret on every request, AgentGraft's runtime verifies the signature, and your user_loader does the actual lookup against your own database.

#How they fit together

Read it bottom-up. A Tool is a Python function. A bunch of tools, plus an entry agent and maybe some specialists, plus a system prompt with policies, all decorated under one Profile, become one Graft's declarative config. That graft lives inside a Workspace. The host app pushes the config via agentgraft_sync, drops one widget tag, and the bubble appears.