hivetrace 1.3.5__py3-none-any.whl → 1.3.6__py3-none-any.whl

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.
@@ -0,0 +1,905 @@
1
+ Metadata-Version: 2.1
2
+ Name: hivetrace
3
+ Version: 1.3.6
4
+ Summary: Hivetrace SDK for monitoring LLM applications
5
+ Home-page: http://hivetrace.ai
6
+ Author: Raft
7
+ Author-email: sales@raftds.com
8
+ Keywords: SDK,monitoring,logging,LLM,AI,Hivetrace
9
+ Classifier: License :: OSI Approved :: Apache Software License
10
+ Requires-Python: >=3.8
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: httpx >=0.28.1
14
+ Requires-Dist: python-dotenv >=1.0.1
15
+ Provides-Extra: all
16
+ Requires-Dist: crewai >=0.95.0 ; extra == 'all'
17
+ Requires-Dist: httpx >=0.28.1 ; extra == 'all'
18
+ Requires-Dist: langchain-community ==0.3.18 ; extra == 'all'
19
+ Requires-Dist: langchain-openai ==0.2.5 ; extra == 'all'
20
+ Requires-Dist: langchain ==0.3.19 ; extra == 'all'
21
+ Requires-Dist: langchain-experimental ==0.3.4 ; extra == 'all'
22
+ Requires-Dist: openai-agents >=0.1.0 ; extra == 'all'
23
+ Requires-Dist: python-dotenv >=1.0.1 ; extra == 'all'
24
+ Provides-Extra: base
25
+ Requires-Dist: httpx >=0.28.1 ; extra == 'base'
26
+ Requires-Dist: python-dotenv >=1.0.1 ; extra == 'base'
27
+ Provides-Extra: crewai
28
+ Requires-Dist: crewai >=0.95.0 ; extra == 'crewai'
29
+ Provides-Extra: langchain
30
+ Requires-Dist: langchain-community ==0.3.18 ; extra == 'langchain'
31
+ Requires-Dist: langchain-openai ==0.2.5 ; extra == 'langchain'
32
+ Requires-Dist: langchain ==0.3.19 ; extra == 'langchain'
33
+ Requires-Dist: langchain-experimental ==0.3.4 ; extra == 'langchain'
34
+ Provides-Extra: openai_agents
35
+ Requires-Dist: openai-agents >=0.1.0 ; extra == 'openai_agents'
36
+
37
+ # Hivetrace SDK
38
+
39
+ ## Overview
40
+
41
+ Hivetrace SDK is designed for integration with the Hivetrace service, providing monitoring of user prompts and LLM responses.
42
+
43
+ ## Installation
44
+
45
+ Install the SDK via pip:
46
+
47
+ ```bash
48
+ pip install hivetrace[base]
49
+ ```
50
+
51
+ ## Usage
52
+
53
+ ```python
54
+ from hivetrace import SyncHivetraceSDK, AsyncHivetraceSDK
55
+ ```
56
+
57
+ ## Synchronous and Asynchronous Clients
58
+
59
+ SDK предоставляет два отдельных клиента: синхронный (`SyncHivetraceSDK`) и асинхронный (`AsyncHivetraceSDK`). Выберите подходящий под ваш режим выполнения.
60
+
61
+ ### Sync Mode
62
+
63
+ #### Инициализация (Sync)
64
+
65
+ ```python
66
+ # Sync client (использует переменные окружения или переданный config)
67
+ client = SyncHivetraceSDK()
68
+ ```
69
+
70
+ #### Отправка пользовательского запроса
71
+
72
+ ```python
73
+ response = client.input(
74
+ application_id="your-application-id", # получен после регистрации приложения в UI
75
+ message="User prompt here",
76
+ )
77
+ ```
78
+
79
+ #### Отправка ответа LLM
80
+
81
+ ```python
82
+ response = client.output(
83
+ application_id="your-application-id",
84
+ message="LLM response here",
85
+ )
86
+ ```
87
+
88
+ ### Async Mode
89
+
90
+ #### Инициализация (Async)
91
+
92
+ ```python
93
+ # Async client (можно использовать как контекстный менеджер)
94
+ client = AsyncHivetraceSDK()
95
+ ```
96
+
97
+ #### Отправка пользовательского запроса
98
+
99
+ ```python
100
+ response = await client.input(
101
+ application_id="your-application-id",
102
+ message="User prompt here",
103
+ )
104
+ ```
105
+
106
+ #### Отправка ответа LLM
107
+
108
+ ```python
109
+ response = await client.output(
110
+ application_id="your-application-id",
111
+ message="LLM response here",
112
+ )
113
+ ```
114
+
115
+ ## Example with Additional Parameters
116
+
117
+ ```python
118
+ response = client.input(
119
+ application_id="your-application-id",
120
+ message="User prompt here",
121
+ additional_parameters={
122
+ "session_id": "your-session-id",
123
+ "user_id": "your-user-id",
124
+ "agents": {
125
+ "agent-1-id": {"name": "Agent 1", "description": "Agent description"},
126
+ "agent-2-id": {"name": "Agent 2"},
127
+ "agent-3-id": {}
128
+ }
129
+ }
130
+ )
131
+ ```
132
+
133
+ > **Note:** `session_id`, `user_id`, and `agent_id` must be valid UUIDs.
134
+
135
+ ## API
136
+
137
+ ### `input`
138
+
139
+ ```python
140
+ # Sync
141
+ def input(application_id: str, message: str, additional_parameters: dict | None = None) -> dict: ...
142
+
143
+ # Async
144
+ async def input(application_id: str, message: str, additional_parameters: dict | None = None) -> dict: ...
145
+ ```
146
+
147
+ Sends a user prompt to Hivetrace.
148
+
149
+ * `application_id`: Application identifier (must be a valid UUID, created in the UI)
150
+ * `message`: User prompt
151
+ * `additional_parameters`: Dictionary of additional parameters (optional)
152
+
153
+ **Response Example:**
154
+
155
+ ```json
156
+ {
157
+ "status": "processed",
158
+ "monitoring_result": {
159
+ "is_toxic": false,
160
+ "type_of_violation": "benign",
161
+ "token_count": 9,
162
+ "token_usage_warning": false,
163
+ "token_usage_unbounded": false
164
+ }
165
+ }
166
+ ```
167
+
168
+ ### `output`
169
+
170
+ ```python
171
+ # Sync
172
+ def output(application_id: str, message: str, additional_parameters: dict | None = None) -> dict: ...
173
+
174
+ # Async
175
+ async def output(application_id: str, message: str, additional_parameters: dict | None = None) -> dict: ...
176
+ ```
177
+
178
+ Sends an LLM response to Hivetrace.
179
+
180
+ * `application_id`: Application identifier (must be a valid UUID, created in the UI)
181
+ * `message`: LLM response
182
+ * `additional_parameters`: Dictionary of additional parameters (optional)
183
+
184
+ **Response Example:**
185
+
186
+ ```json
187
+ {
188
+ "status": "processed",
189
+ "monitoring_result": {
190
+ "is_toxic": false,
191
+ "type_of_violation": "safe",
192
+ "token_count": 21,
193
+ "token_usage_warning": false,
194
+ "token_usage_unbounded": false
195
+ }
196
+ }
197
+ ```
198
+
199
+ ## Sending Requests in Sync Mode
200
+
201
+ ```python
202
+ def main():
203
+ # вариант 1: контекстный менеджер
204
+ with SyncHivetraceSDK() as client:
205
+ response = client.input(
206
+ application_id="your-application-id",
207
+ message="User prompt here",
208
+ )
209
+
210
+ # вариант 2: явное закрытие
211
+ client = SyncHivetraceSDK()
212
+ try:
213
+ response = client.input(
214
+ application_id="your-application-id",
215
+ message="User prompt here",
216
+ )
217
+ finally:
218
+ client.close()
219
+
220
+ main()
221
+ ```
222
+
223
+ ## Sending Requests in Async Mode
224
+
225
+ ```python
226
+ import asyncio
227
+
228
+ async def main():
229
+ # вариант 1: контекстный менеджер
230
+ async with AsyncHivetraceSDK() as client:
231
+ response = await client.input(
232
+ application_id="your-application-id",
233
+ message="User prompt here",
234
+ )
235
+
236
+ # вариант 2: явное закрытие
237
+ client = AsyncHivetraceSDK()
238
+ try:
239
+ response = await client.input(
240
+ application_id="your-application-id",
241
+ message="User prompt here",
242
+ )
243
+ finally:
244
+ await client.close()
245
+
246
+ asyncio.run(main())
247
+ ```
248
+
249
+ ### Closing the Async Client
250
+
251
+ ```python
252
+ await client.close()
253
+ ```
254
+
255
+ ## Configuration
256
+
257
+ The SDK loads configuration from environment variables. The allowed domain (`HIVETRACE_URL`) and API token (`HIVETRACE_ACCESS_TOKEN`) are automatically retrieved from the environment.
258
+
259
+ ### Configuration Sources
260
+
261
+ Hivetrace SDK can retrieve configuration from the following sources:
262
+
263
+ **.env File:**
264
+
265
+ ```bash
266
+ HIVETRACE_URL=https://your-hivetrace-instance.com
267
+ HIVETRACE_ACCESS_TOKEN=your-access-token # obtained in the UI (API Tokens page)
268
+ ```
269
+
270
+ The SDK will automatically load these settings.
271
+
272
+ You can also pass a config dict explicitly when creating a client instance.
273
+ ```bash
274
+ client = SyncHivetraceSDK(
275
+ config={
276
+ "HIVETRACE_URL": HIVETRACE_URL,
277
+ "HIVETRACE_ACCESS_TOKEN": HIVETRACE_ACCESS_TOKEN,
278
+ },
279
+ )
280
+ ```
281
+
282
+ ## Environment Variables
283
+
284
+ Set up your environment variables for easier configuration:
285
+
286
+ ```bash
287
+ # .env file
288
+ HIVETRACE_URL=https://your-hivetrace-instance.com
289
+ HIVETRACE_ACCESS_TOKEN=your-access-token
290
+ HIVETRACE_APP_ID=your-application-id
291
+ ```
292
+
293
+ # CrewAI Integration
294
+
295
+ **Demo repository**
296
+
297
+ [https://github.com/anntish/multiagents-crew-forge](https://github.com/anntish/multiagents-crew-forge)
298
+
299
+ ## Step 1: Install the dependency
300
+
301
+ **What to do:** Add the HiveTrace SDK to your project
302
+
303
+ **Where:** In `requirements.txt` or via pip
304
+
305
+ ```bash
306
+ # Via pip (for quick testing)
307
+ pip install hivetrace[crewai]>=1.3.5
308
+
309
+ # Or add to requirements.txt (recommended)
310
+ echo "hivetrace[crewai]>=1.3.3" >> requirements.txt
311
+ pip install -r requirements.txt
312
+ ```
313
+
314
+ **Why:** The HiveTrace SDK provides decorators and clients for sending agent activity data to the monitoring platform.
315
+
316
+ ---
317
+
318
+ ## Step 2: **ADD** unique IDs for each agent
319
+
320
+ **Example:** In `src/config.py`
321
+
322
+ ```python
323
+ PLANNER_ID = "333e4567-e89b-12d3-a456-426614174001"
324
+ WRITER_ID = "444e4567-e89b-12d3-a456-426614174002"
325
+ EDITOR_ID = "555e4567-e89b-12d3-a456-426614174003"
326
+ ```
327
+
328
+ **Why agents need IDs:** HiveTrace tracks each agent individually. A UUID ensures the agent can be uniquely identified in the monitoring system.
329
+
330
+ ---
331
+
332
+ ## Step 3: Create an agent mapping
333
+
334
+ **What to do:** Map agent roles to their HiveTrace IDs
335
+
336
+ **Example:** In `src/agents.py` (where your agents are defined)
337
+
338
+ ```python
339
+ from crewai import Agent
340
+ # ADD: import agent IDs
341
+ from src.config import EDITOR_ID, PLANNER_ID, WRITER_ID
342
+
343
+ # ADD: mapping for HiveTrace (REQUIRED!)
344
+ agent_id_mapping = {
345
+ "Content Planner": { # ← Exactly the same as Agent(role="Content Planner")
346
+ "id": PLANNER_ID,
347
+ "description": "Creates content plans"
348
+ },
349
+ "Content Writer": { # ← Exactly the same as Agent(role="Content Writer")
350
+ "id": WRITER_ID,
351
+ "description": "Writes high-quality articles"
352
+ },
353
+ "Editor": { # ← Exactly the same as Agent(role="Editor")
354
+ "id": EDITOR_ID,
355
+ "description": "Edits and improves articles"
356
+ },
357
+ }
358
+
359
+ # Your existing agents (NO CHANGES)
360
+ planner = Agent(
361
+ role="Content Planner", # ← Must match key in agent_id_mapping
362
+ goal="Create a structured content plan for the given topic",
363
+ backstory="You are an experienced analyst...",
364
+ verbose=True,
365
+ )
366
+
367
+ writer = Agent(
368
+ role="Content Writer", # ← Must match key in agent_id_mapping
369
+ goal="Write an informative and engaging article",
370
+ backstory="You are a talented writer...",
371
+ verbose=True,
372
+ )
373
+
374
+ editor = Agent(
375
+ role="Editor", # ← Must match key in agent_id_mapping
376
+ goal="Improve the article",
377
+ backstory="You are an experienced editor...",
378
+ verbose=True,
379
+ )
380
+ ```
381
+
382
+ **Important:** The keys in `agent_id_mapping` must **exactly** match the `role` of your agents. Otherwise, HiveTrace will not be able to associate activity with the correct agent.
383
+
384
+ ---
385
+
386
+ ## Step 4: Integrate with tools (if used)
387
+
388
+ **What to do:** Add HiveTrace support to tools
389
+
390
+ **Example:** In `src/tools.py`
391
+
392
+ ```python
393
+ from crewai.tools import BaseTool
394
+ from typing import Optional
395
+
396
+ class WordCountTool(BaseTool):
397
+ name: str = "WordCountTool"
398
+ description: str = "Count words, characters and sentences in text"
399
+ # ADD: HiveTrace field (REQUIRED!)
400
+ agent_id: Optional[str] = None
401
+
402
+ def _run(self, text: str) -> str:
403
+ word_count = len(text.split())
404
+ return f"Word count: {word_count}"
405
+ ```
406
+
407
+ **Example:** In `src/agents.py`
408
+
409
+ ```python
410
+ from src.tools import WordCountTool
411
+ from src.config import PLANNER_ID, WRITER_ID, EDITOR_ID
412
+
413
+ # ADD: create tools for each agent
414
+ planner_tools = [WordCountTool()]
415
+ writer_tools = [WordCountTool()]
416
+ editor_tools = [WordCountTool()]
417
+
418
+ # ADD: assign tools to agents
419
+ for tool in planner_tools:
420
+ tool.agent_id = PLANNER_ID
421
+
422
+ for tool in writer_tools:
423
+ tool.agent_id = WRITER_ID
424
+
425
+ for tool in editor_tools:
426
+ tool.agent_id = EDITOR_ID
427
+
428
+ # Use tools in agents
429
+ planner = Agent(
430
+ role="Content Planner",
431
+ tools=planner_tools, # ← Agent-specific tools
432
+ # ... other parameters
433
+ )
434
+ ```
435
+
436
+ **Why:** HiveTrace tracks tool usage. The `agent_id` field in the tool class and its assignment let HiveTrace know which agent used which tool.
437
+
438
+ ---
439
+
440
+ ## Step 5: Initialize HiveTrace in FastAPI (if used)
441
+
442
+ **What to do:** Add the HiveTrace client to the application lifecycle
443
+
444
+ **Example:** In `main.py`
445
+
446
+ ```python
447
+ from contextlib import asynccontextmanager
448
+ from fastapi import FastAPI
449
+ # ADD: import HiveTrace SDK
450
+ from hivetrace import SyncHivetraceSDK
451
+ from src.config import HIVETRACE_ACCESS_TOKEN, HIVETRACE_URL
452
+
453
+ @asynccontextmanager
454
+ async def lifespan(app: FastAPI):
455
+ # ADD: initialize HiveTrace client
456
+ hivetrace = SyncHivetraceSDK(
457
+ config={
458
+ "HIVETRACE_URL": HIVETRACE_URL,
459
+ "HIVETRACE_ACCESS_TOKEN": HIVETRACE_ACCESS_TOKEN,
460
+ }
461
+ )
462
+ # Store client in app state
463
+ app.state.hivetrace = hivetrace
464
+ try:
465
+ yield
466
+ finally:
467
+ # IMPORTANT: close connection on shutdown
468
+ hivetrace.close()
469
+
470
+ app = FastAPI(lifespan=lifespan)
471
+ ```
472
+
473
+ ---
474
+
475
+ ## Step 6: Integrate into business logic
476
+
477
+ **What to do:** Wrap Crew creation with the HiveTrace decorator
478
+
479
+ **Example:** In `src/services/topic_service.py`
480
+
481
+ ```python
482
+ import uuid
483
+ from typing import Optional
484
+ from crewai import Crew
485
+ # ADD: HiveTrace imports
486
+ from hivetrace import SyncHivetraceSDK
487
+ from hivetrace import crewai_trace as trace
488
+
489
+ from src.agents import agent_id_mapping, planner, writer, editor
490
+ from src.tasks import plan_task, write_task, edit_task
491
+ from src.config import HIVETRACE_APP_ID
492
+
493
+ def process_topic(
494
+ topic: str,
495
+ hivetrace: SyncHivetraceSDK, # ← ADD parameter
496
+ user_id: Optional[str] = None,
497
+ session_id: Optional[str] = None,
498
+ ):
499
+ # ADD: generate unique conversation ID
500
+ agent_conversation_id = str(uuid.uuid4())
501
+
502
+ # ADD: common trace parameters
503
+ common_params = {
504
+ "agent_conversation_id": agent_conversation_id,
505
+ "user_id": user_id,
506
+ "session_id": session_id,
507
+ }
508
+
509
+ # ADD: log user request
510
+ hivetrace.input(
511
+ application_id=HIVETRACE_APP_ID,
512
+ message=f"Requesting information from agents on topic: {topic}",
513
+ additional_parameters={
514
+ **common_params,
515
+ "agents": agent_id_mapping, # ← pass agent mapping
516
+ },
517
+ )
518
+
519
+ # ADD: @trace decorator for monitoring Crew
520
+ @trace(
521
+ hivetrace=hivetrace,
522
+ application_id=HIVETRACE_APP_ID,
523
+ agent_id_mapping=agent_id_mapping, # ← REQUIRED!
524
+ )
525
+ def create_crew():
526
+ return Crew(
527
+ agents=[planner, writer, editor],
528
+ tasks=[plan_task, write_task, edit_task],
529
+ verbose=True,
530
+ )
531
+
532
+ # Execute with monitoring
533
+ crew = create_crew()
534
+ result = crew.kickoff(
535
+ inputs={"topic": topic},
536
+ **common_params # ← pass common parameters
537
+ )
538
+
539
+ return {
540
+ "result": result.raw,
541
+ "execution_details": {**common_params, "status": "completed"},
542
+ }
543
+ ```
544
+
545
+ **How it works:**
546
+
547
+ 1. **`agent_conversation_id`** — unique ID for grouping all actions under a single request
548
+ 2. **`hivetrace.input()`** — sends the user’s request to HiveTrace for inspection
549
+ 3. **`@trace`**:
550
+
551
+ * Intercepts all agent actions inside the Crew
552
+ * Sends data about each step to HiveTrace
553
+ * Associates actions with specific agents via `agent_id_mapping`
554
+ 4. **`**common_params`** — passes metadata into `crew.kickoff()` so all events are linked
555
+
556
+ **Critical:** The `@trace` decorator must be applied to the function that creates and returns the `Crew`, **not** the function that calls `kickoff()`.
557
+
558
+ ---
559
+
560
+ ## Step 7: Update FastAPI endpoints (if used)
561
+
562
+ **What to do:** Pass the HiveTrace client to the business logic
563
+
564
+ **Example:** In `src/routers/topic_router.py`
565
+
566
+ ```python
567
+ from fastapi import APIRouter, Body, Request
568
+ # ADD: import HiveTrace type
569
+ from hivetrace import SyncHivetraceSDK
570
+
571
+ from src.services.topic_service import process_topic
572
+ from src.config import SESSION_ID, USER_ID
573
+
574
+ router = APIRouter(prefix="/api")
575
+
576
+ @router.post("/process-topic")
577
+ async def api_process_topic(request: Request, request_body: dict = Body(...)):
578
+ # ADD: get HiveTrace client from app state
579
+ hivetrace: SyncHivetraceSDK = request.app.state.hivetrace
580
+
581
+ return process_topic(
582
+ topic=request_body["topic"],
583
+ hivetrace=hivetrace, # ← pass client
584
+ user_id=USER_ID,
585
+ session_id=SESSION_ID,
586
+ )
587
+ ```
588
+
589
+ **Why:** The API endpoint must pass the HiveTrace client to the business logic so monitoring data can be sent.
590
+
591
+ ---
592
+
593
+ ## 🚨 Common mistakes
594
+
595
+ 1. **Role mismatch** — make sure keys in `agent_id_mapping` exactly match `role` in agents
596
+ 2. **Missing `agent_id_mapping`** — the `@trace` decorator must receive the mapping
597
+ 3. **Decorator on wrong function** — `@trace` must be applied to the Crew creation function, not `kickoff`
598
+ 4. **Client not closed** — remember to call `hivetrace.close()` in the lifespan
599
+ 5. **Invalid credentials** — check your HiveTrace environment variables
600
+
601
+
602
+ # LangChain Integration
603
+
604
+ **Demo repository**
605
+
606
+ [https://github.com/anntish/multiagents-langchain-forge](https://github.com/anntish/multiagents-langchain-forge)
607
+
608
+ This project implements monitoring of a multi-agent system in LangChain via the HiveTrace SDK.
609
+
610
+ ### Step 1. Install Dependencies
611
+
612
+ ```bash
613
+ pip install hivetrace[langchain]>=1.3.5
614
+ # optional: add to requirements.txt and install
615
+ echo "hivetrace[langchain]>=1.3.3" >> requirements.txt
616
+ pip install -r requirements.txt
617
+ ```
618
+
619
+ What the package provides: SDK clients (sync/async), a universal callback for LangChain agents, and ready-to-use calls for sending inputs/logs/outputs to HiveTrace.
620
+
621
+ ### Step 2. Configure Environment Variables
622
+
623
+ * `HIVETRACE_URL`: HiveTrace address
624
+ * `HIVETRACE_ACCESS_TOKEN`: HiveTrace access token
625
+ * `HIVETRACE_APP_ID`: your application ID in HiveTrace
626
+ * `OPENAI_API_KEY`: key for the LLM provider (example with OpenAI)
627
+ * Additionally: `OPENAI_MODEL`, `USER_ID`, `SESSION_ID`
628
+
629
+ ### Step 3. Assign Fixed UUIDs to Your Agents
630
+
631
+ Create a dictionary of fixed UUIDs for all "agent nodes" (e.g., orchestrator, specialized agents). This ensures unambiguous identification in tracing.
632
+
633
+ Example: file `src/core/constants.py`:
634
+
635
+ ```python
636
+ PREDEFINED_AGENT_IDS = {
637
+ "MainHub": "111e1111-e89b-12d3-a456-426614174099",
638
+ "text_agent": "222e2222-e89b-12d3-a456-426614174099",
639
+ "math_agent": "333e3333-e89b-12d3-a456-426614174099",
640
+ "pre_text_agent": "444e4444-e89b-12d3-a456-426614174099",
641
+ "pre_math_agent": "555e5555-e89b-12d3-a456-426614174099",
642
+ }
643
+ ```
644
+
645
+ Tip: dictionary keys must match the actual node names appearing in logs (`tool`/agent name in LangChain calls).
646
+
647
+ ### Step 4. Attach the Callback to Executors and Tools
648
+
649
+ Create and use `AgentLoggingCallback` — it should be passed:
650
+
651
+ * as a callback in `AgentExecutor` (orchestrator), and
652
+ * as `callback_handler` in your tools/agent wrappers (`BaseTool`).
653
+
654
+ Example: file `src/core/orchestrator.py` (fragment):
655
+
656
+ ```python
657
+ from hivetrace.adapters.langchain import AgentLoggingCallback
658
+ from langchain.agents import AgentExecutor, create_openai_tools_agent
659
+ from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
660
+
661
+ class OrchestratorAgent:
662
+ def __init__(self, llm, predefined_agent_ids=None):
663
+ self.llm = llm
664
+ self.logging_callback = AgentLoggingCallback(
665
+ default_root_name="MainHub",
666
+ predefined_agent_ids=predefined_agent_ids,
667
+ )
668
+ # Example: wrapper agents as tools
669
+ # MathAgentTool/TextAgentTool internally pass self.logging_callback further
670
+ agent = create_openai_tools_agent(self.llm, self.tools, ChatPromptTemplate.from_messages([
671
+ ("system", "You are the orchestrator agent of a multi-agent system."),
672
+ MessagesPlaceholder(variable_name="chat_history", optional=True),
673
+ ("human", "{input}"),
674
+ MessagesPlaceholder(variable_name="agent_scratchpad"),
675
+ ]))
676
+ self.executor = AgentExecutor(
677
+ agent=agent,
678
+ tools=self.tools,
679
+ verbose=True,
680
+ callbacks=[self.logging_callback],
681
+ )
682
+ ```
683
+
684
+ Important: all nested agents/tools that create their own `AgentExecutor` or inherit from `BaseTool` must also receive this `callback_handler` so their steps are included in tracing.
685
+
686
+ ### Step 5. One-Line Integration in a Business Method
687
+
688
+ Use the `run_with_tracing` helper from `hivetrace/adapters/langchain/api.py`. It:
689
+
690
+ * logs the input with agent mapping and metadata;
691
+ * calls your orchestrator;
692
+ * collects and sends accumulated logs/final answer.
693
+
694
+ Minimal example (script):
695
+
696
+ ```python
697
+ import os, uuid
698
+ from langchain_openai import ChatOpenAI
699
+ from src.core.orchestrator import OrchestratorAgent
700
+ from src.core.constants import PREDEFINED_AGENT_IDS
701
+ from hivetrace.adapters.langchain import run_with_tracing
702
+
703
+ llm = ChatOpenAI(model=os.getenv("OPENAI_MODEL", "gpt-4o-mini"), temperature=0.2, streaming=False)
704
+ orchestrator = OrchestratorAgent(llm, predefined_agent_ids=PREDEFINED_AGENT_IDS)
705
+
706
+ result = run_with_tracing(
707
+ orchestrator=orchestrator,
708
+ query="Format this text and count the number of words",
709
+ application_id=os.getenv("HIVETRACE_APP_ID"),
710
+ user_id=os.getenv("USER_ID"),
711
+ session_id=os.getenv("SESSION_ID"),
712
+ conversation_id=str(uuid.uuid4()),
713
+ )
714
+ print(result)
715
+ ```
716
+
717
+ FastAPI variant (handler fragment):
718
+
719
+ ```python
720
+ from fastapi import APIRouter, Request
721
+ from hivetrace.adapters.langchain import run_with_tracing
722
+ import uuid
723
+
724
+ router = APIRouter()
725
+
726
+ @router.post("/query")
727
+ async def process_query(payload: dict, request: Request):
728
+ orchestrator = request.app.state.orchestrator
729
+ conv_id = str(uuid.uuid4()) # always create a new agent_conversation_id for each request to group agent work for the same question
730
+ result = run_with_tracing(
731
+ orchestrator=orchestrator,
732
+ query=payload["query"],
733
+ application_id=request.app.state.HIVETRACE_APP_ID,
734
+ user_id=request.app.state.USER_ID,
735
+ session_id=request.app.state.SESSION_ID,
736
+ conversation_id=conv_id,
737
+ )
738
+ return {"status": "success", "result": result}
739
+ ```
740
+
741
+ ### Step 6. Reusing the HiveTrace Client (Optional)
742
+
743
+ Helpers automatically create a short-lived client if none is provided. If you want to reuse a client — create it once during the application's lifecycle and pass it to helpers.
744
+
745
+ FastAPI (lifespan):
746
+
747
+ ```python
748
+ from contextlib import asynccontextmanager
749
+ from fastapi import FastAPI
750
+ from hivetrace import SyncHivetraceSDK
751
+
752
+ @asynccontextmanager
753
+ async def lifespan(app: FastAPI):
754
+ hivetrace = SyncHivetraceSDK()
755
+ app.state.hivetrace = hivetrace
756
+ try:
757
+ yield
758
+ finally:
759
+ hivetrace.close()
760
+
761
+ app = FastAPI(lifespan=lifespan)
762
+ ```
763
+
764
+ Then:
765
+
766
+ ```python
767
+ result = run_with_tracing(
768
+ orchestrator=orchestrator,
769
+ query=payload.query,
770
+ hivetrace=request.app.state.hivetrace, # pass your own client
771
+ application_id=request.app.state.HIVETRACE_APP_ID,
772
+ )
773
+ ```
774
+
775
+ ### How Logs Look in HiveTrace
776
+
777
+ * **Agent nodes**: orchestrator nodes and specialized "agent wrappers" (`text_agent`, `math_agent`, etc.).
778
+ * **Actual tools**: low-level tools (e.g., `text_analyzer`, `text_formatter`) are logged on start/end events.
779
+ * **Service records**: automatically added `return_result` (returning result to parent) and `final_answer` (final answer of the root node) steps.
780
+
781
+ This gives a clear call graph with data flow direction and the final answer.
782
+
783
+ ### Common Mistakes and How to Avoid Them
784
+
785
+ * **Name mismatch**: key in `PREDEFINED_AGENT_IDS` must match the node/tool name in logs.
786
+ * **No agent mapping**: either pass `agents_mapping` to `run_with_tracing` or define `predefined_agent_ids` in `AgentLoggingCallback` — the SDK will build the mapping automatically.
787
+ * **Callback not attached**: add `AgentLoggingCallback` to all `AgentExecutor` and `BaseTool` wrappers via the `callback_handler` parameter.
788
+ * **Client not closed**: use lifespan/context manager for `SyncHivetraceSDK`.
789
+
790
+
791
+ # OpenAI Agents Integration
792
+
793
+ **Demo repository**
794
+
795
+ [https://github.com/anntish/openai-agents-forge](https://github.com/anntish/openai-agents-forge)
796
+
797
+ ### 1. Installation
798
+
799
+ ```bash
800
+ pip install hivetrace[openai_agents]==1.3.5
801
+ ```
802
+
803
+ ---
804
+
805
+ ### 2. Environment Setup
806
+
807
+ Set the environment variables (via `.env` or export):
808
+
809
+ ```bash
810
+ HIVETRACE_URL=http://localhost:8000 # Your HiveTrace URL
811
+ HIVETRACE_ACCESS_TOKEN=ht_... # Your HiveTrace access token
812
+ HIVETRACE_APPLICATION_ID=00000000-...-0000 # Your HiveTrace application ID
813
+
814
+ SESSION_ID=
815
+ USERID=
816
+
817
+ OPENAI_API_KEY=
818
+ OPENAI_BASE_URL=https://api.openai.com/v1
819
+ OPENAI_MODEL=gpt-4o-mini
820
+ ```
821
+
822
+ ---
823
+
824
+ ### 3. Attach the Trace Processor in Code
825
+
826
+ Add 3 lines before creating/using your agents:
827
+
828
+ ```python
829
+ from agents import set_trace_processors
830
+ from hivetrace.adapters.openai_agents.tracing import HivetraceOpenAIAgentProcessor
831
+
832
+ set_trace_processors([
833
+ HivetraceOpenAIAgentProcessor() # will take config from env
834
+ ])
835
+ ```
836
+
837
+ Alternative (explicit configuration if you don’t want to rely on env):
838
+
839
+ ```python
840
+ from agents import set_trace_processors
841
+ from hivetrace import SyncHivetraceSDK
842
+ from hivetrace.adapters.openai_agents.tracing import HivetraceOpenAIAgentProcessor
843
+
844
+ hivetrace = SyncHivetraceSDK(config={
845
+ "HIVETRACE_URL": "http://localhost:8000",
846
+ "HIVETRACE_ACCESS_TOKEN": "ht_...",
847
+ })
848
+
849
+ set_trace_processors([
850
+ HivetraceOpenAIAgentProcessor(
851
+ application_id="00000000-0000-0000-0000-000000000000",
852
+ hivetrace_instance=hivetrace,
853
+ )
854
+ ])
855
+ ```
856
+
857
+ Important:
858
+
859
+ * Register the processor only once at app startup.
860
+ * Attach it before the first agent run (`Runner.run(...)` / `Runner.run_sync(...)`).
861
+
862
+ ---
863
+
864
+ ### 4. Minimal "Before/After" Example
865
+
866
+ Before:
867
+
868
+ ```python
869
+ from agents import Agent, Runner
870
+
871
+ assistant = Agent(name="Assistant", instructions="Be helpful.")
872
+ print(Runner.run_sync(assistant, "Hi!"))
873
+ ```
874
+
875
+ After (with HiveTrace monitoring):
876
+
877
+ ```python
878
+ from agents import Agent, Runner, set_trace_processors
879
+ from hivetrace.adapters.openai_agents.tracing import HivetraceOpenAIAgentProcessor
880
+
881
+ set_trace_processors([HivetraceOpenAIAgentProcessor()])
882
+
883
+ assistant = Agent(name="Assistant", instructions="Be helpful.")
884
+ print(Runner.run_sync(assistant, "Hi!"))
885
+ ```
886
+
887
+ From this moment, all agent calls, handoffs, and tool invocations will be logged in HiveTrace.
888
+
889
+ ---
890
+
891
+ ### 5. Tool Tracing
892
+
893
+ If you use tools, decorate them with `@function_tool` so their calls are automatically traced:
894
+
895
+ ```python
896
+ from agents import function_tool
897
+
898
+ @function_tool(description_override="Adds two numbers")
899
+ def calculate_sum(a: int, b: int) -> int:
900
+ return a + b
901
+ ```
902
+
903
+ Add this tool to your agent’s `tools=[...]` — and its calls will appear in HiveTrace with inputs/outputs.
904
+
905
+ ---