Quick Start
Let’s build your first AI agent in under 5 minutes.
What You’ll Build
A simple agent that responds to messages with streaming AI responses. By the end, you’ll have a working /api/chat endpoint.
Install
pip install "django-ai-sdk[haystack]"The haystack extra pulls in Haystack and the components agents run on. That’s all you need to start.
Want the full set of extras (MCP, DRF views, document parsing)?
pip install "django-ai-sdk[all]"all extra includes DRF routers and serializers, but the DRF path is still in active development: use the Ninja views for production.Configure Django
Add the app to your INSTALLED_APPS:
# settings.py
INSTALLED_APPS = [
# ... your apps
"django_ai_sdk",
]Run migrations:
python manage.py migrateThis creates tables for conversation storage. You won’t need to think about them: the SDK handles it automatically.
Create an Agent
An agent is just a Python class with personality:
# agents.py
from django.conf import settings
from django_ai_sdk import Agent
from django_ai_sdk.adapters.base import Stream
from django_ai_sdk.agents import auto_register
from django_ai_sdk.common import prompt
from django_ai_sdk.pipelines.haystack import ToolAgent, ToolAgentConfig
from django_ai_sdk.protocols.vercel import VercelProtocolHandler
from django_ai_sdk.storage.db import DbStorageAdapter
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.utils import Secret
@auto_register
class ShakespeareAgent(Agent):
"""An agent that speaks like Shakespeare."""
name = "Shakespeare Bot"
model = settings.AI_SDK_DEFAULT_MODEL
instructions = prompt(
"You are a helpful assistant who speaks in Shakespearean English. "
"Use thee, thou, and other Elizabethan expressions. "
"Be poetic but always answer the user's question."
)
protocol = VercelProtocolHandler
storage_adapter = DbStorageAdapter
async def get_pipeline_adapter(self, thread_id=None, user=None):
generator = OpenAIChatGenerator(
model=self.get_model(),
api_key=Secret.from_token(settings.OPENAI_API_KEY),
api_base_url=getattr(settings, "OPENAI_API_URL", None),
)
tool_agent = ToolAgent(
config=ToolAgentConfig(
model=self.get_model(),
system_prompt=self.get_system_prompt(),
tools=await self.get_tools(thread_id=thread_id or "", user=user),
),
generator=generator,
)
return Stream(
pipeline=tool_agent.pipeline(),
generator=generator,
storage_adapter=await self.get_storage_adapter(thread_id),
)Three things to note:
- name: What to call your agent
- instructions: How it should behave (the system prompt)
- get_pipeline_adapter: Returns the
Streamthat powers streaming chat
OpenAIChatGenerator works with any OpenAI-compatible endpoint. Point OPENAI_API_URL at a local server (vLLM, Ollama, llama.cpp) or leave it unset for OpenAI. Every other AI_SDK_* setting you might need is listed in the Settings Reference.
That’s it. No complex configuration. No framework setup.
Register Your Agent
Your agent must be registered before it can be used. Add it to AI_SDK_AGENTS in your settings.py:
# settings.py
AI_SDK_AGENTS = [
"your_app.agents.ShakespeareAgent",
]The SDK loads these classes at startup. Each agent gets a stable UUID derived from its module and class name, so you can retrieve it anywhere:
from django_ai_sdk.agents.services import AgentService
# Get an agent by its stable ID
agent = await AgentService.get(agent_id)Agents are also registered automatically by the @auto_register decorator: AI_SDK_AGENTS just makes sure the module is imported.
Wire It to a View
Connect your agent to Django Ninja:
# views.py
from ninja import Router
from django_ai_sdk.agents.services import AgentService
from django_ai_sdk.views.schemas import ChatRequest
router = Router()
@router.post("/chat")
async def chat(request, payload: ChatRequest):
"""Chat with Shakespeare Bot."""
agent = await AgentService.get(payload.agent_id)
return await agent.as_view(payload.messages, user=request.user)The as_view() method handles everything:
- Protocol conversion (Vercel AI SDK Data Stream Protocol in,
ChatMessages internally) - Building the pipeline adapter and streaming to the model
- Returning an SSE
StreamingHttpResponse
Add to URLs
# urls.py
from ninja import NinjaAPI
from your_app.views import router
api = NinjaAPI()
api.add_router("/", router)
urlpatterns = [
path("api/", api.urls),
]Test It
Start your server:
python manage.py runserverSend a message:
curl -X POST http://localhost:8000/api/chat \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-d '{
"messages": [{"role": "user", "parts": [{"type": "text", "text": "Hello!"}]}],
"agent_id": "your-agent-uuid"
}'You’ll see a streaming response:
data: {"type":"start","messageId":"msg_abc123"}
data: {"type":"text-start","id":"text_001"}
data: {"type":"text-delta","id":"text_001","delta":"Hark!"}
data: {"type":"text-delta","id":"text_001","delta":" Good"}
data: {"type":"text-delta","id":"text_001","delta":" morrow"}
data: {"type":"text-delta","id":"text_001","delta":" to"}
data: {"type":"text-delta","id":"text_001","delta":" thee!"}
data: {"type":"text-end","id":"text_001"}
data: {"type":"finish"}
data: [DONE]You did it! Your agent is live and streaming responses.
as_view() converted the protocol messages to internal ChatMessages, get_pipeline_adapter() built a ToolAgent pipeline and returned a Stream, Haystack streamed chunks normalized into StreamEvents, and the events were serialized to the Vercel protocol over SSE. All in about 50 lines of code.