Get started
Quickstart
From an empty Django app to a working chat widget in seven steps and roughly five minutes.
5 min read
This walks through embedding AgentGraft in a Django app you already own. By the end you'll have a chat bubble in the corner of your site that calls real Python functions in your codebase, with the agent's prompt, tool definitions, and routing all defined in one Python file under version control.
If you don't have an AgentGraft account yet, sign up at agentgraft.com/accounts/signup/ first โ that takes about thirty seconds and mints your first graft automatically.
#Step 1 โ Save your credentials
Right after signup, AgentGraft shows the four credentials for your default graft exactly once. The api_key is the only piece you cannot recover โ it's stored as a hash in our database. Copy all four into a password manager or your project's .env file before you click Continue.
AGENTGRAFT_API_BASE=https://agentgraft.com
AGENTGRAFT_GRAFT_ID=018f3a7c-...
AGENTGRAFT_PUBLIC_KEY=pk_live_...
AGENTGRAFT_API_KEY=sk_live_...
AGENTGRAFT_WEBHOOK_SECRET=whsec_...
#Step 2 โ Install the SDK
The SDK is a single PyPI package. Install the Django extra to get the management command, webhook view, and template tag.
pip install agentgraft[django]
# or: uv add agentgraft[django]
#Step 3 โ Register the Django adapter
Add the SDK's Django app to INSTALLED_APPS and a single settings dict that maps a profile name to your credentials. The profile system lets one host app run multiple chat experiences side by side; for now you only need the default profile.
# settings.py
INSTALLED_APPS = [
# ...
"agentgraft.django",
]
AGENTGRAFT = {
"config_module": "myapp.agentgraft_config",
"profiles": {
"default": {
"api_base": os.environ["AGENTGRAFT_API_BASE"],
"api_key": os.environ["AGENTGRAFT_API_KEY"],
"public_key": os.environ["AGENTGRAFT_PUBLIC_KEY"],
"graft_id": os.environ["AGENTGRAFT_GRAFT_ID"],
"webhook_secret": os.environ["AGENTGRAFT_WEBHOOK_SECRET"],
},
},
}
#Step 4 โ Mount the webhook URL
AgentGraft dispatches tool calls to your host app over HTTP. The SDK ships a Django view that receives those calls, verifies the HMAC signature, and runs the right function from your config. Mount it under any prefix you like โ /agentgraft/ is the convention.
# urls.py
from django.urls import include, path
urlpatterns = [
# ...
path("agentgraft/", include("agentgraft.django.urls")),
]
#Step 5 โ Write your config file
This is the file. Tools, agents, and the system prompt all live here, decorated with the SDK's helpers. Type hints become JSON schemas the LLM sees; docstrings become tool descriptions; the @ag.user_loader resolves the external user id passed by the widget back to a real Django user object.
# myapp/agentgraft_config.py
import agentgraft as ag
from myapp.models import Dataset, User
@ag.user_loader
def load_user(external_id: str) -> User:
return User.objects.get(pk=external_id)
@ag.tool
def list_datasets(user: User) -> list[dict]:
"""List the user's datasets."""
return list(user.datasets.values("id", "name"))
@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}
@ag.agent(entry=True, tools=[list_datasets, get_dataset])
def helper():
"""You help users explore their datasets. Always call a tool
before answering data questions; never invent values."""
ag.graft(
name="MyApp",
identity="You are MyApp's data assistant.",
voice="Be concise. Cite the dataset name when quoting figures.",
)
#Step 6 โ Sync your config to AgentGraft
The local file is the source of truth, but the runtime that drives the chat lives on agentgraft.com. The sync command serialises every decorator-registered tool, agent, and prompt block, and POSTs the whole declarative bundle to your graft in one atomic transaction. Run it once now, and again every time you edit the config file.
python manage.py agentgraft_sync
#Step 7 โ Drop the widget tag
One template tag in any Django template renders the chat bubble. The widget paints into a closed Shadow DOM so it can never collide with your site's CSS. The SDK figures out the user identity from request.user, signs the HMAC, and wires the script to your graft automatically.
{% load agentgraft %}
<!doctype html>
<html>
<body>
<h1>My app</h1>
<!-- ... -->
{% agentgraft_widget %}
</body>
</html>
#What success looks like
Reload any page in your app. A small round face pops into the bottom-right corner and starts watching your cursor. Click it. Type "what datasets do I have?". The widget streams an answer over Server-Sent Events; meanwhile the agent has called list_datasets against your real Django ORM and cited the result. No iframes, no client build step, no third-party JavaScript on the page beyond the one script tag the template emits.
#Where to next
The Quickstart deliberately glosses over a few things. To go deeper: the Concepts page explains the vocabulary (workspace, graft, profile, policy) โ it's the shortest read in the docs and the highest leverage. The SDK page is the full decorator reference. The Wire protocol page covers the webhook contract for anyone debugging tool calls.