django-agent-runtime 0.3.5__tar.gz → 0.3.11__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. {django_agent_runtime-0.3.5/django_agent_runtime.egg-info → django_agent_runtime-0.3.11}/PKG-INFO +645 -8
  2. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/README.md +639 -6
  3. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/api/views.py +2 -2
  4. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/conf.py +1 -1
  5. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11/django_agent_runtime.egg-info}/PKG-INFO +645 -8
  6. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/django_agent_runtime.egg-info/SOURCES.txt +2 -0
  7. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/django_agent_runtime.egg-info/requires.txt +7 -1
  8. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/management/commands/runagent.py +66 -5
  9. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/pyproject.toml +8 -2
  10. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/runtime/__init__.py +7 -0
  11. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/runtime/registry.py +70 -7
  12. django_agent_runtime-0.3.11/runtime/tools.py +179 -0
  13. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/LICENSE +0 -0
  14. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/MANIFEST.in +0 -0
  15. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/__init__.py +0 -0
  16. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/admin.py +0 -0
  17. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/api/__init__.py +0 -0
  18. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/api/permissions.py +0 -0
  19. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/api/serializers.py +0 -0
  20. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/apps.py +0 -0
  21. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/django_agent_runtime.egg-info/dependency_links.txt +0 -0
  22. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/django_agent_runtime.egg-info/top_level.txt +0 -0
  23. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/examples/__init__.py +0 -0
  24. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/examples/langgraph_adapter.py +0 -0
  25. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/examples/langgraph_tools.py +0 -0
  26. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/examples/simple_chat.py +0 -0
  27. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/examples/tool_agent.py +0 -0
  28. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/management/__init__.py +0 -0
  29. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/management/commands/__init__.py +0 -0
  30. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/migrations/0001_initial.py +0 -0
  31. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/migrations/0002_persistence_models.py +0 -0
  32. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/migrations/0003_persistenceconversation_active_branch_id_and_more.py +0 -0
  33. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/migrations/0004_add_anonymous_session_id.py +0 -0
  34. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/migrations/__init__.py +0 -0
  35. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/models/__init__.py +0 -0
  36. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/models/base.py +0 -0
  37. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/models/concrete.py +0 -0
  38. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/persistence/__init__.py +0 -0
  39. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/persistence/helpers.py +0 -0
  40. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/persistence/models.py +0 -0
  41. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/persistence/stores.py +0 -0
  42. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/runtime/events/__init__.py +0 -0
  43. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/runtime/events/base.py +0 -0
  44. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/runtime/events/db.py +0 -0
  45. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/runtime/events/redis.py +0 -0
  46. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/runtime/events/sync.py +0 -0
  47. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/runtime/interfaces.py +0 -0
  48. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/runtime/llm/__init__.py +0 -0
  49. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/runtime/llm/anthropic.py +0 -0
  50. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/runtime/llm/litellm_adapter.py +0 -0
  51. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/runtime/llm/openai.py +0 -0
  52. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/runtime/queue/__init__.py +0 -0
  53. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/runtime/queue/base.py +0 -0
  54. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/runtime/queue/postgres.py +0 -0
  55. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/runtime/queue/redis_streams.py +0 -0
  56. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/runtime/queue/sync.py +0 -0
  57. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/runtime/runner.py +0 -0
  58. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/runtime/tracing/__init__.py +0 -0
  59. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/runtime/tracing/langfuse.py +0 -0
  60. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/runtime/tracing/noop.py +0 -0
  61. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/setup.cfg +0 -0
  62. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/tests/test_api.py +0 -0
  63. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/tests/test_events.py +0 -0
  64. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/tests/test_interfaces.py +0 -0
  65. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/tests/test_llm.py +0 -0
  66. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/tests/test_models.py +0 -0
  67. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/tests/test_persistence.py +0 -0
  68. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/tests/test_queue.py +0 -0
  69. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/tests/test_registry.py +0 -0
  70. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/tests/test_runner.py +0 -0
  71. {django_agent_runtime-0.3.5 → django_agent_runtime-0.3.11}/urls.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-agent-runtime
3
- Version: 0.3.5
3
+ Version: 0.3.11
4
4
  Summary: Production-grade AI agent runtime for Django - framework and model agnostic
5
5
  Author: Chris Barry
6
6
  License-Expression: MIT
@@ -37,8 +37,12 @@ Provides-Extra: litellm
37
37
  Requires-Dist: litellm>=1.0.0; extra == "litellm"
38
38
  Provides-Extra: langfuse
39
39
  Requires-Dist: langfuse>=2.0.0; extra == "langfuse"
40
+ Provides-Extra: framework
41
+ Requires-Dist: agent-runtime-framework>=0.1.0; extra == "framework"
42
+ Provides-Extra: recommended
43
+ Requires-Dist: django-agent-runtime[framework,openai,redis]; extra == "recommended"
40
44
  Provides-Extra: all
41
- Requires-Dist: django-agent-runtime[anthropic,langfuse,litellm,openai,redis]; extra == "all"
45
+ Requires-Dist: django-agent-runtime[anthropic,framework,langfuse,litellm,openai,redis]; extra == "all"
42
46
  Provides-Extra: dev
43
47
  Requires-Dist: pytest>=7.0; extra == "dev"
44
48
  Requires-Dist: pytest-django>=4.5; extra == "dev"
@@ -62,6 +66,13 @@ A production-ready Django app for AI agent execution. Provides everything you ne
62
66
 
63
67
  | Version | Date | Changes |
64
68
  |---------|------|---------|
69
+ | **0.3.11** | 2025-01-19 | Add Full Stack Setup Guide for AI agents |
70
+ | **0.3.10** | 2025-01-15 | SSE named events for addEventListener support, flexible registry path format |
71
+ | **0.3.9** | 2025-01-14 | Add `[recommended]` and `[framework]` install extras |
72
+ | **0.3.8** | 2025-01-14 | Add agent-frontend docs, agent framework options (OpenAI, Anthropic, LangGraph) |
73
+ | **0.3.7** | 2025-01-13 | Fix auto-reload signal handler in threaded mode |
74
+ | **0.3.6** | 2025-01-13 | Auto-reload for `runagent` in DEBUG mode (like Django's runserver) |
75
+ | **0.3.5** | 2025-01-13 | Added Recent Updates changelog to README |
65
76
  | **0.3.4** | 2025-01-13 | Documentation updates for message history |
66
77
  | **0.3.3** | 2025-01-13 | Added `conversation.get_message_history()` for retrieving full message sequences |
67
78
  | **0.3.2** | 2025-01-13 | Event visibility system - filter events by `internal`/`debug`/`user` levels |
@@ -84,6 +95,13 @@ A production-ready Django app for AI agent execution. Provides everything you ne
84
95
  ```bash
85
96
  pip install django-agent-runtime
86
97
 
98
+ # Recommended: Redis + OpenAI + agent-runtime-framework
99
+ pip install django-agent-runtime[recommended]
100
+
101
+ # Pick specific extras (comma-separated)
102
+ pip install django-agent-runtime[openai,framework]
103
+ pip install django-agent-runtime[redis,anthropic]
104
+
87
105
  # With LLM providers
88
106
  pip install django-agent-runtime[openai]
89
107
  pip install django-agent-runtime[anthropic]
@@ -91,6 +109,9 @@ pip install django-agent-runtime[anthropic]
91
109
  # With Redis support (recommended for production)
92
110
  pip install django-agent-runtime[redis]
93
111
 
112
+ # With agent-runtime-framework for journey-based agents
113
+ pip install django-agent-runtime[framework]
114
+
94
115
  # Everything
95
116
  pip install django-agent-runtime[all]
96
117
  ```
@@ -645,9 +666,55 @@ python manage.py runagent \
645
666
  --queue-poll-interval 1.0
646
667
  ```
647
668
 
669
+ #### Auto-Reload (Development)
670
+
671
+ In `DEBUG=True` mode, `runagent` automatically reloads when Python files change—just like Django's `runserver`:
672
+
673
+ ```bash
674
+ # Auto-reload enabled by default in DEBUG mode
675
+ python manage.py runagent
676
+
677
+ # Disable auto-reload
678
+ python manage.py runagent --noreload
679
+ ```
680
+
681
+ **Note:** Auto-reload only works in single-process mode. Multi-process mode (`--processes > 1`) automatically disables auto-reload.
682
+
648
683
  ## Frontend Integration
649
684
 
650
- ### JavaScript SSE Client
685
+ ### agent-frontend (Recommended)
686
+
687
+ The easiest way to add a chat UI is with [agent-frontend](https://github.com/makemore/agent-frontend) - a zero-dependency, embeddable chat widget:
688
+
689
+ ```html
690
+ <!-- Include the widget -->
691
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/makemore/agent-frontend@main/dist/chat-widget.css">
692
+ <script src="https://cdn.jsdelivr.net/gh/makemore/agent-frontend@main/dist/chat-widget.js"></script>
693
+
694
+ <!-- Initialize -->
695
+ <script>
696
+ ChatWidget.init({
697
+ backendUrl: 'https://your-api.com',
698
+ agentKey: 'chat-agent',
699
+ title: 'Support Chat',
700
+ primaryColor: '#0066cc',
701
+ });
702
+ </script>
703
+ ```
704
+
705
+ Features:
706
+ - **Zero dependencies** - Pure vanilla JavaScript
707
+ - **SSE streaming** - Real-time token-by-token responses
708
+ - **CSS isolated** - Won't conflict with your existing styles
709
+ - **Dark mode** - Automatic based on system preferences
710
+ - **Session management** - Anonymous sessions out of the box
711
+ - **Demo flows** - Built-in auto-run mode for showcasing agent journeys
712
+
713
+ See the [agent-frontend documentation](https://github.com/makemore/agent-frontend) for full configuration options.
714
+
715
+ ### Custom JavaScript SSE Client
716
+
717
+ If you're building your own UI:
651
718
 
652
719
  ```javascript
653
720
  const eventSource = new EventSource('/api/agents/runs/550e8400.../events/');
@@ -675,29 +742,599 @@ eventSource.addEventListener('run.failed', (event) => {
675
742
  function useAgentRun(runId: string) {
676
743
  const [events, setEvents] = useState<AgentEvent[]>([]);
677
744
  const [status, setStatus] = useState<'running' | 'complete' | 'error'>('running');
678
-
745
+
679
746
  useEffect(() => {
680
747
  const es = new EventSource(`/api/agents/runs/${runId}/events/`);
681
-
748
+
682
749
  es.onmessage = (event) => {
683
750
  const data = JSON.parse(event.data);
684
751
  setEvents(prev => [...prev, data]);
685
-
752
+
686
753
  if (data.type === 'run.succeeded') setStatus('complete');
687
754
  if (data.type === 'run.failed') setStatus('error');
688
755
  };
689
-
756
+
690
757
  return () => es.close();
691
758
  }, [runId]);
692
-
759
+
693
760
  return { events, status };
694
761
  }
695
762
  ```
696
763
 
764
+ ## Agent Framework Options
765
+
766
+ django-agent-runtime is framework-agnostic. You can build agents using:
767
+
768
+ ### Option 1: Direct AgentRuntime (Simple)
769
+
770
+ Best for simple agents or when you want full control:
771
+
772
+ ```python
773
+ from django_agent_runtime.runtime.interfaces import AgentRuntime, RunContext, RunResult
774
+
775
+ class MyAgent(AgentRuntime):
776
+ @property
777
+ def key(self) -> str:
778
+ return "my-agent"
779
+
780
+ async def run(self, ctx: RunContext) -> RunResult:
781
+ # Your agent logic here
782
+ ...
783
+ ```
784
+
785
+ ### Option 2: agent_runtime_framework (Journey-Based)
786
+
787
+ Best for multi-step conversational flows with state management:
788
+
789
+ ```bash
790
+ pip install agent_runtime_framework
791
+ ```
792
+
793
+ ```python
794
+ from agent_runtime_framework.adapters import DjangoRuntimeAdapter
795
+ from agent_runtime_framework import BaseJourneyState, BaseJourneyTools, ToolSchema
796
+ from enum import Enum
797
+
798
+ class QuoteStep(str, Enum):
799
+ WELCOME = "welcome"
800
+ COLLECT_INFO = "collect_info"
801
+ GENERATE_QUOTE = "generate_quote"
802
+ COMPLETE = "complete"
803
+
804
+ class QuoteState(BaseJourneyState[QuoteStep]):
805
+ step: QuoteStep = QuoteStep.WELCOME
806
+ customer_name: str = ""
807
+ coverage_type: str = ""
808
+ # ... state fields
809
+
810
+ class QuoteTools(BaseJourneyTools[QuoteState]):
811
+ async def save_customer_info(self, name: str, coverage: str) -> str:
812
+ self.state.customer_name = name
813
+ self.state.coverage_type = coverage
814
+ self.state.step = QuoteStep.GENERATE_QUOTE
815
+ await self._notify_state_change()
816
+ return f"Got it, {name}! Generating your {coverage} quote..."
817
+
818
+ class QuoteAgent(DjangoRuntimeAdapter[QuoteState, QuoteTools, QuoteStep]):
819
+ @property
820
+ def key(self) -> str:
821
+ return "quote-agent"
822
+
823
+ def get_initial_state(self) -> QuoteState:
824
+ return QuoteState()
825
+
826
+ def get_system_prompt(self, state: QuoteState) -> str:
827
+ prompts = {
828
+ QuoteStep.WELCOME: "Welcome the user and ask what coverage they need.",
829
+ QuoteStep.COLLECT_INFO: "Collect customer name and coverage type.",
830
+ # ...
831
+ }
832
+ return prompts[state.step]
833
+
834
+ def get_tool_schemas(self, state: QuoteState) -> list[ToolSchema]:
835
+ # Return different tools based on current step
836
+ ...
837
+
838
+ def create_tools(self, state, ctx, backend_client) -> QuoteTools:
839
+ return QuoteTools(state=state)
840
+
841
+ async def execute_tool(self, tools, name: str, arguments: dict) -> str:
842
+ return await getattr(tools, name)(**arguments)
843
+
844
+ # Register with django-agent-runtime
845
+ from django_agent_runtime.runtime.registry import register_runtime
846
+ register_runtime(QuoteAgent())
847
+ ```
848
+
849
+ The adapter handles:
850
+ - Converting Django's `RunContext` to framework's `AgentContext`
851
+ - State persistence via Django's checkpoint system
852
+ - Event emission through Django's event bus
853
+ - Returning results in Django's `RunResult` format
854
+
855
+ See [agent_runtime_framework](https://github.com/makemore/agent-runtime-framework) for full documentation.
856
+
857
+ ### Option 3: OpenAI Agents SDK
858
+
859
+ Use OpenAI's official Agents SDK with django-agent-runtime:
860
+
861
+ ```python
862
+ from django_agent_runtime.runtime.interfaces import AgentRuntime, RunContext, RunResult, EventType
863
+ from agents import Agent, Runner
864
+
865
+ class OpenAIAgentRuntime(AgentRuntime):
866
+ @property
867
+ def key(self) -> str:
868
+ return "openai-agent"
869
+
870
+ def __init__(self):
871
+ self.agent = Agent(
872
+ name="Assistant",
873
+ instructions="You are a helpful assistant.",
874
+ model="gpt-4o",
875
+ )
876
+
877
+ async def run(self, ctx: RunContext) -> RunResult:
878
+ # Convert messages to OpenAI format
879
+ user_message = ctx.input_messages[-1]["content"]
880
+
881
+ # Run the OpenAI agent
882
+ result = await Runner.run(self.agent, user_message)
883
+
884
+ # Emit the response
885
+ await ctx.emit(EventType.ASSISTANT_MESSAGE, {
886
+ "content": result.final_output,
887
+ })
888
+
889
+ return RunResult(
890
+ final_output={"response": result.final_output},
891
+ final_messages=[{"role": "assistant", "content": result.final_output}],
892
+ )
893
+ ```
894
+
895
+ ### Option 4: Anthropic Claude with Tool Use
896
+
897
+ Use Anthropic's Claude directly:
898
+
899
+ ```python
900
+ from django_agent_runtime.runtime.interfaces import AgentRuntime, RunContext, RunResult, EventType
901
+ import anthropic
902
+
903
+ class ClaudeAgent(AgentRuntime):
904
+ @property
905
+ def key(self) -> str:
906
+ return "claude-agent"
907
+
908
+ def __init__(self):
909
+ self.client = anthropic.AsyncAnthropic()
910
+
911
+ async def run(self, ctx: RunContext) -> RunResult:
912
+ messages = [
913
+ {"role": m["role"], "content": m["content"]}
914
+ for m in ctx.input_messages
915
+ ]
916
+
917
+ response = await self.client.messages.create(
918
+ model="claude-sonnet-4-20250514",
919
+ max_tokens=1024,
920
+ messages=messages,
921
+ )
922
+
923
+ content = response.content[0].text
924
+
925
+ await ctx.emit(EventType.ASSISTANT_MESSAGE, {"content": content})
926
+
927
+ return RunResult(
928
+ final_output={"response": content},
929
+ final_messages=[{"role": "assistant", "content": content}],
930
+ )
931
+ ```
932
+
933
+ ### Option 5: LangGraph
934
+
935
+ Wrap LangGraph agents:
936
+
937
+ ```python
938
+ from django_agent_runtime.runtime.interfaces import AgentRuntime, RunContext, RunResult, EventType
939
+ from langgraph.graph import StateGraph
940
+
941
+ class LangGraphRuntime(AgentRuntime):
942
+ @property
943
+ def key(self) -> str:
944
+ return "langgraph-agent"
945
+
946
+ def __init__(self):
947
+ self.graph = self._build_graph()
948
+
949
+ def _build_graph(self) -> StateGraph:
950
+ # Build your LangGraph here
951
+ ...
952
+
953
+ async def run(self, ctx: RunContext) -> RunResult:
954
+ # Run the graph
955
+ result = await self.graph.ainvoke({
956
+ "messages": ctx.input_messages,
957
+ })
958
+
959
+ final_message = result["messages"][-1]
960
+ await ctx.emit(EventType.ASSISTANT_MESSAGE, {
961
+ "content": final_message.content,
962
+ })
963
+
964
+ return RunResult(
965
+ final_output={"response": final_message.content},
966
+ final_messages=result["messages"],
967
+ )
968
+ ```
969
+
697
970
  ## Related Packages
698
971
 
972
+ - [agent-frontend](https://github.com/makemore/agent-frontend) - Zero-dependency embeddable chat widget for AI agents
973
+ - [agent-runtime-framework](https://github.com/makemore/agent-runtime-framework) - Journey-based conversational agents with state management
699
974
  - [agent-runtime-core](https://pypi.org/project/agent-runtime-core/) - The framework-agnostic core library (used internally)
700
975
 
976
+ ---
977
+
978
+ ## Full Stack Setup Guide (For AI Agents)
979
+
980
+ This guide explains how to set up the complete agent stack from scratch. It's designed to be followed by another AI agent or developer.
981
+
982
+ ### Package Overview
983
+
984
+ | Package | Purpose | Install |
985
+ |---------|---------|---------|
986
+ | **django-agent-runtime** | Django app for agent execution, API, queues, events | `pip install django-agent-runtime[recommended]` |
987
+ | **agent-runtime-core** | Core abstractions (tools, events, config) | Included with django-agent-runtime |
988
+ | **agent-runtime-framework** | Journey-based agents with state management | Included with `[recommended]` or `[framework]` |
989
+ | **@makemore/agent-frontend** | Embeddable chat widget (vanilla JS) | `npm install @makemore/agent-frontend` |
990
+
991
+ ### Step 1: Create Django Project
992
+
993
+ ```bash
994
+ # Create project directory
995
+ mkdir my_agent_project && cd my_agent_project
996
+
997
+ # Create virtual environment
998
+ python -m venv venv
999
+ source venv/bin/activate # On Windows: venv\Scripts\activate
1000
+
1001
+ # Install Django and agent runtime with recommended extras
1002
+ pip install django django-agent-runtime[recommended]
1003
+
1004
+ # Create Django project
1005
+ django-admin startproject config .
1006
+ python manage.py startapp agents
1007
+ ```
1008
+
1009
+ ### Step 2: Configure Django Settings
1010
+
1011
+ ```python
1012
+ # config/settings.py
1013
+
1014
+ INSTALLED_APPS = [
1015
+ 'django.contrib.admin',
1016
+ 'django.contrib.auth',
1017
+ 'django.contrib.contenttypes',
1018
+ 'django.contrib.sessions',
1019
+ 'django.contrib.messages',
1020
+ 'django.contrib.staticfiles',
1021
+ 'rest_framework',
1022
+ 'django_agent_runtime',
1023
+ 'agents',
1024
+ ]
1025
+
1026
+ # Agent Runtime Configuration
1027
+ DJANGO_AGENT_RUNTIME = {
1028
+ 'QUEUE_BACKEND': 'postgres',
1029
+ 'EVENT_BUS_BACKEND': 'db',
1030
+ 'MODEL_PROVIDER': 'openai',
1031
+ 'DEFAULT_MODEL': 'gpt-4o',
1032
+ 'RUNTIME_REGISTRY': [
1033
+ 'agents.runtimes:register_agents',
1034
+ ],
1035
+ }
1036
+
1037
+ # Required for API
1038
+ REST_FRAMEWORK = {
1039
+ 'DEFAULT_AUTHENTICATION_CLASSES': [
1040
+ 'rest_framework.authentication.SessionAuthentication',
1041
+ ],
1042
+ 'DEFAULT_PERMISSION_CLASSES': [
1043
+ 'rest_framework.permissions.AllowAny', # For testing; tighten in production
1044
+ ],
1045
+ }
1046
+
1047
+ # CORS for frontend (install django-cors-headers)
1048
+ CORS_ALLOW_ALL_ORIGINS = True # For development only
1049
+ ```
1050
+
1051
+ ### Step 3: Create a Simple Agent
1052
+
1053
+ ```python
1054
+ # agents/runtimes.py
1055
+ from django_agent_runtime.runtime.interfaces import (
1056
+ AgentRuntime, RunContext, RunResult, EventType
1057
+ )
1058
+ from django_agent_runtime.runtime.registry import register_runtime
1059
+ from django_agent_runtime.runtime.llm import get_llm_client
1060
+
1061
+
1062
+ class HelloAgent(AgentRuntime):
1063
+ """A simple agent that responds to messages."""
1064
+
1065
+ @property
1066
+ def key(self) -> str:
1067
+ return "hello-agent"
1068
+
1069
+ async def run(self, ctx: RunContext) -> RunResult:
1070
+ llm = get_llm_client()
1071
+
1072
+ # Add system message
1073
+ messages = [
1074
+ {"role": "system", "content": "You are a friendly assistant. Keep responses brief."},
1075
+ *ctx.input_messages
1076
+ ]
1077
+
1078
+ # Call LLM
1079
+ response = await llm.generate(messages)
1080
+ content = response.message.get("content", "")
1081
+
1082
+ # Emit for real-time streaming
1083
+ await ctx.emit(EventType.ASSISTANT_MESSAGE, {
1084
+ "content": content,
1085
+ "role": "assistant",
1086
+ })
1087
+
1088
+ return RunResult(
1089
+ final_output={"response": content},
1090
+ final_messages=[response.message],
1091
+ )
1092
+
1093
+
1094
+ def register_agents():
1095
+ """Called by django-agent-runtime on startup."""
1096
+ register_runtime(HelloAgent())
1097
+ ```
1098
+
1099
+ ### Step 4: Set Up API URLs
1100
+
1101
+ ```python
1102
+ # agents/urls.py
1103
+ from django.urls import path, include
1104
+ from rest_framework.routers import DefaultRouter
1105
+ from django_agent_runtime.api.views import (
1106
+ BaseAgentRunViewSet,
1107
+ BaseAgentConversationViewSet,
1108
+ sync_event_stream,
1109
+ )
1110
+
1111
+ router = DefaultRouter()
1112
+ router.register(r'conversations', BaseAgentConversationViewSet, basename='conversation')
1113
+ router.register(r'runs', BaseAgentRunViewSet, basename='run')
1114
+
1115
+ urlpatterns = [
1116
+ path('', include(router.urls)),
1117
+ path('runs/<str:run_id>/events/', sync_event_stream, name='run-events'),
1118
+ ]
1119
+ ```
1120
+
1121
+ ```python
1122
+ # config/urls.py
1123
+ from django.contrib import admin
1124
+ from django.urls import path, include
1125
+
1126
+ urlpatterns = [
1127
+ path('admin/', admin.site.urls),
1128
+ path('api/agents/', include('agents.urls')),
1129
+ ]
1130
+ ```
1131
+
1132
+ ### Step 5: Run Migrations and Start Services
1133
+
1134
+ ```bash
1135
+ # Set your OpenAI API key
1136
+ export OPENAI_API_KEY="sk-..."
1137
+
1138
+ # Run migrations
1139
+ python manage.py migrate
1140
+
1141
+ # Start Django server (terminal 1)
1142
+ python manage.py runserver
1143
+
1144
+ # Start agent workers (terminal 2)
1145
+ python manage.py runagent
1146
+ ```
1147
+
1148
+ ### Step 6: Test the API
1149
+
1150
+ ```bash
1151
+ # Create a conversation
1152
+ curl -X POST http://localhost:8000/api/agents/conversations/ \
1153
+ -H "Content-Type: application/json" \
1154
+ -d '{"agent_key": "hello-agent"}'
1155
+
1156
+ # Response: {"id": "conv-uuid-here", ...}
1157
+
1158
+ # Create a run (replace CONV_ID)
1159
+ curl -X POST http://localhost:8000/api/agents/runs/ \
1160
+ -H "Content-Type: application/json" \
1161
+ -d '{
1162
+ "conversation_id": "CONV_ID",
1163
+ "agent_key": "hello-agent",
1164
+ "messages": [{"role": "user", "content": "Hello! What can you do?"}]
1165
+ }'
1166
+
1167
+ # Response: {"id": "run-uuid-here", "status": "queued", ...}
1168
+
1169
+ # Stream events (replace RUN_ID)
1170
+ curl -N http://localhost:8000/api/agents/runs/RUN_ID/events/
1171
+ ```
1172
+
1173
+ ### Step 7: Add Frontend to Next.js
1174
+
1175
+ In your Next.js project:
1176
+
1177
+ ```bash
1178
+ npm install @makemore/agent-frontend
1179
+ ```
1180
+
1181
+ Create a chat component:
1182
+
1183
+ ```tsx
1184
+ // components/AgentChat.tsx
1185
+ 'use client';
1186
+
1187
+ import { useEffect } from 'react';
1188
+
1189
+ export default function AgentChat() {
1190
+ useEffect(() => {
1191
+ // Import and initialize the widget
1192
+ import('@makemore/agent-frontend/dist/chat-widget.js').then(() => {
1193
+ // @ts-ignore
1194
+ window.ChatWidget?.init({
1195
+ backendUrl: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000',
1196
+ agentKey: 'hello-agent',
1197
+ title: 'AI Assistant',
1198
+ subtitle: 'Ask me anything!',
1199
+ primaryColor: '#0066cc',
1200
+ position: 'bottom-right',
1201
+ apiEndpoints: {
1202
+ conversations: '/api/agents/conversations/',
1203
+ runs: '/api/agents/runs/',
1204
+ events: '/api/agents/runs/{runId}/events/',
1205
+ },
1206
+ });
1207
+ });
1208
+
1209
+ return () => {
1210
+ // @ts-ignore
1211
+ window.ChatWidget?.destroy?.();
1212
+ };
1213
+ }, []);
1214
+
1215
+ return null; // Widget renders itself
1216
+ }
1217
+ ```
1218
+
1219
+ Or use CDN in your layout:
1220
+
1221
+ ```tsx
1222
+ // app/layout.tsx
1223
+ export default function RootLayout({ children }) {
1224
+ return (
1225
+ <html>
1226
+ <head>
1227
+ <link
1228
+ rel="stylesheet"
1229
+ href="https://unpkg.com/@makemore/agent-frontend/dist/chat-widget.css"
1230
+ />
1231
+ </head>
1232
+ <body>
1233
+ {children}
1234
+ <script src="https://unpkg.com/@makemore/agent-frontend/dist/chat-widget.js" />
1235
+ <script
1236
+ dangerouslySetInnerHTML={{
1237
+ __html: `
1238
+ document.addEventListener('DOMContentLoaded', function() {
1239
+ ChatWidget.init({
1240
+ backendUrl: '${process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000'}',
1241
+ agentKey: 'hello-agent',
1242
+ title: 'AI Assistant',
1243
+ primaryColor: '#0066cc',
1244
+ });
1245
+ });
1246
+ `,
1247
+ }}
1248
+ />
1249
+ </body>
1250
+ </html>
1251
+ );
1252
+ }
1253
+ ```
1254
+
1255
+ ### Step 8: Configure CORS (Production)
1256
+
1257
+ ```bash
1258
+ pip install django-cors-headers
1259
+ ```
1260
+
1261
+ ```python
1262
+ # config/settings.py
1263
+ INSTALLED_APPS = [
1264
+ 'corsheaders',
1265
+ ...
1266
+ ]
1267
+
1268
+ MIDDLEWARE = [
1269
+ 'corsheaders.middleware.CorsMiddleware',
1270
+ ...
1271
+ ]
1272
+
1273
+ CORS_ALLOWED_ORIGINS = [
1274
+ 'http://localhost:3000', # Next.js dev
1275
+ 'https://your-frontend.com',
1276
+ ]
1277
+ ```
1278
+
1279
+ ### Complete File Structure
1280
+
1281
+ ```
1282
+ my_agent_project/
1283
+ ├── config/
1284
+ │ ├── __init__.py
1285
+ │ ├── settings.py
1286
+ │ ├── urls.py
1287
+ │ └── wsgi.py
1288
+ ├── agents/
1289
+ │ ├── __init__.py
1290
+ │ ├── runtimes.py # Your agent implementations
1291
+ │ └── urls.py # API routes
1292
+ ├── manage.py
1293
+ └── requirements.txt
1294
+
1295
+ # Next.js frontend (separate repo)
1296
+ my-frontend/
1297
+ ├── app/
1298
+ │ └── layout.tsx # Include chat widget here
1299
+ ├── components/
1300
+ │ └── AgentChat.tsx # Or as a component
1301
+ └── package.json
1302
+ ```
1303
+
1304
+ ### Environment Variables
1305
+
1306
+ **Django (.env):**
1307
+ ```bash
1308
+ OPENAI_API_KEY=sk-...
1309
+ DATABASE_URL=postgres://... # For production
1310
+ REDIS_URL=redis://... # For production
1311
+ DEBUG=True
1312
+ ```
1313
+
1314
+ **Next.js (.env.local):**
1315
+ ```bash
1316
+ NEXT_PUBLIC_API_URL=http://localhost:8000
1317
+ ```
1318
+
1319
+ ### Quick Reference Commands
1320
+
1321
+ ```bash
1322
+ # Django
1323
+ python manage.py runserver # Start API server
1324
+ python manage.py runagent # Start agent workers
1325
+ python manage.py migrate # Run migrations
1326
+
1327
+ # Next.js
1328
+ npm run dev # Start frontend
1329
+
1330
+ # Testing
1331
+ curl -X POST http://localhost:8000/api/agents/conversations/ \
1332
+ -H "Content-Type: application/json" \
1333
+ -d '{"agent_key": "hello-agent"}'
1334
+ ```
1335
+
1336
+ ---
1337
+
701
1338
  ## Contributing
702
1339
 
703
1340
  Contributions are welcome! Please feel free to submit a Pull Request.