agno 2.3.16__py3-none-any.whl → 2.3.18__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.
- agno/agent/__init__.py +2 -0
- agno/agent/agent.py +4 -53
- agno/agent/remote.py +351 -0
- agno/client/__init__.py +3 -0
- agno/client/os.py +2669 -0
- agno/db/base.py +20 -0
- agno/db/mongo/async_mongo.py +11 -0
- agno/db/mongo/mongo.py +10 -0
- agno/db/mysql/async_mysql.py +9 -0
- agno/db/mysql/mysql.py +9 -0
- agno/db/postgres/async_postgres.py +9 -0
- agno/db/postgres/postgres.py +9 -0
- agno/db/postgres/utils.py +3 -2
- agno/db/sqlite/async_sqlite.py +9 -0
- agno/db/sqlite/sqlite.py +11 -1
- agno/exceptions.py +23 -0
- agno/knowledge/chunking/semantic.py +123 -46
- agno/knowledge/reader/csv_reader.py +1 -1
- agno/knowledge/reader/field_labeled_csv_reader.py +1 -1
- agno/knowledge/reader/json_reader.py +1 -1
- agno/models/google/gemini.py +5 -0
- agno/os/app.py +108 -25
- agno/os/auth.py +25 -1
- agno/os/interfaces/a2a/a2a.py +7 -6
- agno/os/interfaces/a2a/router.py +13 -13
- agno/os/interfaces/agui/agui.py +5 -3
- agno/os/interfaces/agui/router.py +23 -16
- agno/os/interfaces/base.py +7 -7
- agno/os/interfaces/slack/router.py +6 -6
- agno/os/interfaces/slack/slack.py +7 -7
- agno/os/interfaces/whatsapp/router.py +29 -6
- agno/os/interfaces/whatsapp/whatsapp.py +11 -8
- agno/os/managers.py +326 -0
- agno/os/mcp.py +651 -79
- agno/os/router.py +125 -18
- agno/os/routers/agents/router.py +65 -22
- agno/os/routers/agents/schema.py +16 -4
- agno/os/routers/database.py +5 -0
- agno/os/routers/evals/evals.py +93 -11
- agno/os/routers/evals/utils.py +6 -6
- agno/os/routers/knowledge/knowledge.py +104 -16
- agno/os/routers/memory/memory.py +124 -7
- agno/os/routers/metrics/metrics.py +21 -4
- agno/os/routers/session/session.py +141 -12
- agno/os/routers/teams/router.py +40 -14
- agno/os/routers/teams/schema.py +12 -4
- agno/os/routers/traces/traces.py +54 -4
- agno/os/routers/workflows/router.py +223 -117
- agno/os/routers/workflows/schema.py +65 -1
- agno/os/schema.py +38 -12
- agno/os/utils.py +87 -166
- agno/remote/__init__.py +3 -0
- agno/remote/base.py +484 -0
- agno/run/workflow.py +1 -0
- agno/team/__init__.py +2 -0
- agno/team/remote.py +287 -0
- agno/team/team.py +25 -54
- agno/tracing/exporter.py +10 -6
- agno/tracing/setup.py +2 -1
- agno/utils/agent.py +58 -1
- agno/utils/http.py +68 -20
- agno/utils/os.py +0 -0
- agno/utils/remote.py +23 -0
- agno/vectordb/chroma/chromadb.py +452 -16
- agno/vectordb/pgvector/pgvector.py +7 -0
- agno/vectordb/redis/redisdb.py +1 -1
- agno/workflow/__init__.py +2 -0
- agno/workflow/agent.py +2 -2
- agno/workflow/remote.py +222 -0
- agno/workflow/types.py +0 -73
- agno/workflow/workflow.py +119 -68
- {agno-2.3.16.dist-info → agno-2.3.18.dist-info}/METADATA +1 -1
- {agno-2.3.16.dist-info → agno-2.3.18.dist-info}/RECORD +76 -66
- {agno-2.3.16.dist-info → agno-2.3.18.dist-info}/WHEEL +0 -0
- {agno-2.3.16.dist-info → agno-2.3.18.dist-info}/licenses/LICENSE +0 -0
- {agno-2.3.16.dist-info → agno-2.3.18.dist-info}/top_level.txt +0 -0
agno/remote/base.py
ADDED
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
import time
|
|
2
|
+
from abc import abstractmethod
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from datetime import date
|
|
5
|
+
from typing import TYPE_CHECKING, Any, AsyncIterator, Dict, List, Optional, Sequence, Tuple, Union
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
|
|
9
|
+
from agno.db.base import SessionType
|
|
10
|
+
from agno.media import Audio, File, Image, Video
|
|
11
|
+
from agno.models.message import Message
|
|
12
|
+
from agno.models.response import ToolExecution
|
|
13
|
+
from agno.run.agent import RunOutput, RunOutputEvent
|
|
14
|
+
from agno.run.team import TeamRunOutput, TeamRunOutputEvent
|
|
15
|
+
from agno.run.workflow import WorkflowRunOutput, WorkflowRunOutputEvent
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from fastapi import UploadFile
|
|
19
|
+
|
|
20
|
+
from agno.client import AgentOSClient
|
|
21
|
+
from agno.os.routers.evals.schemas import EvalSchema
|
|
22
|
+
from agno.os.routers.knowledge.schemas import (
|
|
23
|
+
ConfigResponseSchema,
|
|
24
|
+
ContentResponseSchema,
|
|
25
|
+
ContentStatusResponse,
|
|
26
|
+
VectorSearchResult,
|
|
27
|
+
)
|
|
28
|
+
from agno.os.routers.memory.schemas import OptimizeMemoriesResponse, UserMemorySchema, UserStatsSchema
|
|
29
|
+
from agno.os.routers.metrics.schemas import DayAggregatedMetrics, MetricsResponse
|
|
30
|
+
from agno.os.routers.traces.schemas import TraceDetail, TraceNode, TraceSessionStats, TraceSummary
|
|
31
|
+
from agno.os.schema import (
|
|
32
|
+
AgentSessionDetailSchema,
|
|
33
|
+
ConfigResponse,
|
|
34
|
+
PaginatedResponse,
|
|
35
|
+
RunSchema,
|
|
36
|
+
SessionSchema,
|
|
37
|
+
TeamRunSchema,
|
|
38
|
+
TeamSessionDetailSchema,
|
|
39
|
+
WorkflowRunSchema,
|
|
40
|
+
WorkflowSessionDetailSchema,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass
|
|
45
|
+
class RemoteDb:
|
|
46
|
+
id: str
|
|
47
|
+
client: "AgentOSClient"
|
|
48
|
+
session_table_name: Optional[str] = None
|
|
49
|
+
knowledge_table_name: Optional[str] = None
|
|
50
|
+
memory_table_name: Optional[str] = None
|
|
51
|
+
metrics_table_name: Optional[str] = None
|
|
52
|
+
eval_table_name: Optional[str] = None
|
|
53
|
+
traces_table_name: Optional[str] = None
|
|
54
|
+
spans_table_name: Optional[str] = None
|
|
55
|
+
culture_table_name: Optional[str] = None
|
|
56
|
+
|
|
57
|
+
@classmethod
|
|
58
|
+
def from_config(
|
|
59
|
+
cls,
|
|
60
|
+
db_id: str,
|
|
61
|
+
client: "AgentOSClient",
|
|
62
|
+
config: "ConfigResponse",
|
|
63
|
+
) -> Optional["RemoteDb"]:
|
|
64
|
+
"""Create a RemoteDb instance from an AgentResponse/TeamResponse/WorkflowResponse and ConfigResponse.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
response: The agent, team, or workflow response containing the db_id.
|
|
68
|
+
client: The AgentOSClient for remote operations.
|
|
69
|
+
config: The ConfigResponse containing database table information.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
RemoteDb instance if db_id is present, None otherwise.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
session_table_name = None
|
|
76
|
+
knowledge_table_name = None
|
|
77
|
+
memory_table_name = None
|
|
78
|
+
metrics_table_name = None
|
|
79
|
+
eval_table_name = None
|
|
80
|
+
traces_table_name = None
|
|
81
|
+
|
|
82
|
+
if config and config.session and config.session.dbs is not None:
|
|
83
|
+
session_dbs = [db for db in config.session.dbs if db.db_id == db_id]
|
|
84
|
+
session_table_name = session_dbs[0].tables[0] if session_dbs and session_dbs[0].tables else None
|
|
85
|
+
|
|
86
|
+
if config and config.knowledge and config.knowledge.dbs is not None:
|
|
87
|
+
knowledge_dbs = [db for db in config.knowledge.dbs if db.db_id == db_id]
|
|
88
|
+
knowledge_table_name = knowledge_dbs[0].tables[0] if knowledge_dbs and knowledge_dbs[0].tables else None
|
|
89
|
+
|
|
90
|
+
if config and config.memory and config.memory.dbs is not None:
|
|
91
|
+
memory_dbs = [db for db in config.memory.dbs if db.db_id == db_id]
|
|
92
|
+
memory_table_name = memory_dbs[0].tables[0] if memory_dbs and memory_dbs[0].tables else None
|
|
93
|
+
|
|
94
|
+
if config and config.metrics and config.metrics.dbs is not None:
|
|
95
|
+
metrics_dbs = [db for db in config.metrics.dbs if db.db_id == db_id]
|
|
96
|
+
metrics_table_name = metrics_dbs[0].tables[0] if metrics_dbs and metrics_dbs[0].tables else None
|
|
97
|
+
|
|
98
|
+
if config and config.evals and config.evals.dbs is not None:
|
|
99
|
+
eval_dbs = [db for db in config.evals.dbs if db.db_id == db_id]
|
|
100
|
+
eval_table_name = eval_dbs[0].tables[0] if eval_dbs and eval_dbs[0].tables else None
|
|
101
|
+
|
|
102
|
+
if config and config.traces and config.traces.dbs is not None:
|
|
103
|
+
traces_dbs = [db for db in config.traces.dbs if db.db_id == db_id]
|
|
104
|
+
traces_table_name = traces_dbs[0].tables[0] if traces_dbs and traces_dbs[0].tables else None
|
|
105
|
+
|
|
106
|
+
return cls(
|
|
107
|
+
id=db_id,
|
|
108
|
+
client=client,
|
|
109
|
+
session_table_name=session_table_name,
|
|
110
|
+
knowledge_table_name=knowledge_table_name,
|
|
111
|
+
memory_table_name=memory_table_name,
|
|
112
|
+
metrics_table_name=metrics_table_name,
|
|
113
|
+
eval_table_name=eval_table_name,
|
|
114
|
+
traces_table_name=traces_table_name,
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
# SESSIONS
|
|
118
|
+
async def get_sessions(self, **kwargs: Any) -> "PaginatedResponse[SessionSchema]":
|
|
119
|
+
return await self.client.get_sessions(**kwargs)
|
|
120
|
+
|
|
121
|
+
async def get_session(
|
|
122
|
+
self, session_id: str, **kwargs: Any
|
|
123
|
+
) -> Union["AgentSessionDetailSchema", "TeamSessionDetailSchema", "WorkflowSessionDetailSchema"]:
|
|
124
|
+
return await self.client.get_session(session_id, **kwargs)
|
|
125
|
+
|
|
126
|
+
async def get_session_runs(
|
|
127
|
+
self, session_id: str, **kwargs: Any
|
|
128
|
+
) -> List[Union["RunSchema", "TeamRunSchema", "WorkflowRunSchema"]]:
|
|
129
|
+
return await self.client.get_session_runs(session_id, **kwargs)
|
|
130
|
+
|
|
131
|
+
async def create_session(
|
|
132
|
+
self,
|
|
133
|
+
session_id: Optional[str] = None,
|
|
134
|
+
session_name: Optional[str] = None,
|
|
135
|
+
session_state: Optional[Dict[str, Any]] = None,
|
|
136
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
137
|
+
user_id: Optional[str] = None,
|
|
138
|
+
agent_id: Optional[str] = None,
|
|
139
|
+
team_id: Optional[str] = None,
|
|
140
|
+
workflow_id: Optional[str] = None,
|
|
141
|
+
**kwargs: Any,
|
|
142
|
+
) -> Union["AgentSessionDetailSchema", "TeamSessionDetailSchema", "WorkflowSessionDetailSchema"]:
|
|
143
|
+
return await self.client.create_session(
|
|
144
|
+
session_id=session_id,
|
|
145
|
+
session_name=session_name,
|
|
146
|
+
session_state=session_state,
|
|
147
|
+
metadata=metadata,
|
|
148
|
+
user_id=user_id,
|
|
149
|
+
agent_id=agent_id,
|
|
150
|
+
team_id=team_id,
|
|
151
|
+
workflow_id=workflow_id,
|
|
152
|
+
**kwargs,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
async def get_session_run(
|
|
156
|
+
self, session_id: str, run_id: str, **kwargs: Any
|
|
157
|
+
) -> Union["RunSchema", "TeamRunSchema", "WorkflowRunSchema"]:
|
|
158
|
+
return await self.client.get_session_run(session_id, run_id, **kwargs)
|
|
159
|
+
|
|
160
|
+
async def rename_session(
|
|
161
|
+
self, session_id: str, session_name: str, **kwargs: Any
|
|
162
|
+
) -> Union["AgentSessionDetailSchema", "TeamSessionDetailSchema", "WorkflowSessionDetailSchema"]:
|
|
163
|
+
return await self.client.rename_session(session_id, session_name, **kwargs)
|
|
164
|
+
|
|
165
|
+
async def update_session(
|
|
166
|
+
self, session_id: str, session_type: SessionType, **kwargs: Any
|
|
167
|
+
) -> Union["AgentSessionDetailSchema", "TeamSessionDetailSchema", "WorkflowSessionDetailSchema"]:
|
|
168
|
+
return await self.client.update_session(session_id=session_id, session_type=session_type, **kwargs)
|
|
169
|
+
|
|
170
|
+
async def delete_session(self, session_id: str, **kwargs: Any) -> None:
|
|
171
|
+
return await self.client.delete_session(session_id, **kwargs)
|
|
172
|
+
|
|
173
|
+
async def delete_sessions(self, session_ids: List[str], session_types: List[SessionType], **kwargs: Any) -> None:
|
|
174
|
+
return await self.client.delete_sessions(session_ids, session_types, **kwargs)
|
|
175
|
+
|
|
176
|
+
# MEMORIES
|
|
177
|
+
async def create_memory(self, memory: str, topics: List[str], user_id: str, **kwargs: Any) -> "UserMemorySchema":
|
|
178
|
+
return await self.client.create_memory(memory=memory, topics=topics, user_id=user_id, **kwargs)
|
|
179
|
+
|
|
180
|
+
async def delete_memory(self, memory_id: str, **kwargs: Any) -> None:
|
|
181
|
+
return await self.client.delete_memory(memory_id, **kwargs)
|
|
182
|
+
|
|
183
|
+
async def delete_memories(self, memory_ids: List[str], **kwargs: Any) -> None:
|
|
184
|
+
return await self.client.delete_memories(memory_ids, **kwargs)
|
|
185
|
+
|
|
186
|
+
async def get_memory(self, memory_id: str, **kwargs: Any) -> "UserMemorySchema":
|
|
187
|
+
return await self.client.get_memory(memory_id, **kwargs)
|
|
188
|
+
|
|
189
|
+
async def get_memories(self, user_id: Optional[str] = None, **kwargs: Any) -> "PaginatedResponse[UserMemorySchema]":
|
|
190
|
+
return await self.client.list_memories(user_id, **kwargs)
|
|
191
|
+
|
|
192
|
+
async def update_memory(self, memory_id: str, **kwargs: Any) -> "UserMemorySchema":
|
|
193
|
+
return await self.client.update_memory(memory_id, **kwargs)
|
|
194
|
+
|
|
195
|
+
async def get_user_memory_stats(self, **kwargs: Any) -> "PaginatedResponse[UserStatsSchema]":
|
|
196
|
+
return await self.client.get_user_memory_stats(**kwargs)
|
|
197
|
+
|
|
198
|
+
async def optimize_memories(self, **kwargs: Any) -> "OptimizeMemoriesResponse":
|
|
199
|
+
return await self.client.optimize_memories(**kwargs)
|
|
200
|
+
|
|
201
|
+
async def get_memory_topics(self, **kwargs: Any) -> List[str]:
|
|
202
|
+
return await self.client.get_memory_topics(**kwargs)
|
|
203
|
+
|
|
204
|
+
# TRACES
|
|
205
|
+
async def get_traces(self, **kwargs: Any) -> "PaginatedResponse[TraceSummary]":
|
|
206
|
+
return await self.client.get_traces(**kwargs)
|
|
207
|
+
|
|
208
|
+
async def get_trace(self, trace_id: str, **kwargs: Any) -> Union["TraceDetail", "TraceNode"]:
|
|
209
|
+
return await self.client.get_trace(trace_id, **kwargs)
|
|
210
|
+
|
|
211
|
+
async def get_trace_session_stats(self, **kwargs: Any) -> "PaginatedResponse[TraceSessionStats]":
|
|
212
|
+
return await self.client.get_trace_session_stats(**kwargs)
|
|
213
|
+
|
|
214
|
+
# EVALS
|
|
215
|
+
async def get_eval_runs(self, **kwargs: Any) -> "PaginatedResponse[EvalSchema]":
|
|
216
|
+
return await self.client.list_eval_runs(**kwargs)
|
|
217
|
+
|
|
218
|
+
async def get_eval_run(self, eval_run_id: str, **kwargs: Any) -> "EvalSchema":
|
|
219
|
+
return await self.client.get_eval_run(eval_run_id, **kwargs)
|
|
220
|
+
|
|
221
|
+
async def delete_eval_runs(self, eval_run_ids: List[str], **kwargs: Any) -> None:
|
|
222
|
+
return await self.client.delete_eval_runs(eval_run_ids, **kwargs)
|
|
223
|
+
|
|
224
|
+
async def update_eval_run(self, eval_run_id: str, **kwargs: Any) -> "EvalSchema":
|
|
225
|
+
return await self.client.update_eval_run(eval_run_id, **kwargs)
|
|
226
|
+
|
|
227
|
+
async def create_eval_run(self, **kwargs: Any) -> Optional["EvalSchema"]:
|
|
228
|
+
return await self.client.run_eval(**kwargs)
|
|
229
|
+
|
|
230
|
+
# METRICS
|
|
231
|
+
async def get_metrics(
|
|
232
|
+
self, starting_date: Optional[date] = None, ending_date: Optional[date] = None, **kwargs: Any
|
|
233
|
+
) -> "MetricsResponse":
|
|
234
|
+
return await self.client.get_metrics(starting_date=starting_date, ending_date=ending_date, **kwargs)
|
|
235
|
+
|
|
236
|
+
async def refresh_metrics(self, **kwargs: Any) -> List["DayAggregatedMetrics"]:
|
|
237
|
+
return await self.client.refresh_metrics(**kwargs)
|
|
238
|
+
|
|
239
|
+
# OTHER
|
|
240
|
+
async def migrate_database(self, target_version: Optional[str] = None) -> None:
|
|
241
|
+
"""Migrate the database to a target version.
|
|
242
|
+
|
|
243
|
+
Args:
|
|
244
|
+
target_version: Target version to migrate to
|
|
245
|
+
"""
|
|
246
|
+
|
|
247
|
+
return await self.client.migrate_database(self.id, target_version)
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
@dataclass
|
|
251
|
+
class RemoteKnowledge:
|
|
252
|
+
client: "AgentOSClient"
|
|
253
|
+
contents_db: Optional[RemoteDb] = None
|
|
254
|
+
|
|
255
|
+
async def get_config(self, headers: Optional[Dict[str, str]] = None) -> "ConfigResponseSchema":
|
|
256
|
+
return await self.client.get_knowledge_config(
|
|
257
|
+
db_id=self.contents_db.id if self.contents_db else None, headers=headers
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
async def search_knowledge(self, query: str, **kwargs: Any) -> "PaginatedResponse[VectorSearchResult]":
|
|
261
|
+
return await self.client.search_knowledge(query, **kwargs)
|
|
262
|
+
|
|
263
|
+
async def upload_content(
|
|
264
|
+
self,
|
|
265
|
+
name: Optional[str] = None,
|
|
266
|
+
description: Optional[str] = None,
|
|
267
|
+
url: Optional[str] = None,
|
|
268
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
269
|
+
file: Optional[Union[File, "UploadFile"]] = None,
|
|
270
|
+
text_content: Optional[str] = None,
|
|
271
|
+
reader_id: Optional[str] = None,
|
|
272
|
+
chunker: Optional[str] = None,
|
|
273
|
+
chunk_size: Optional[int] = None,
|
|
274
|
+
chunk_overlap: Optional[int] = None,
|
|
275
|
+
db_id: Optional[str] = None,
|
|
276
|
+
**kwargs: Any,
|
|
277
|
+
) -> "ContentResponseSchema":
|
|
278
|
+
return await self.client.upload_knowledge_content(
|
|
279
|
+
name=name,
|
|
280
|
+
description=description,
|
|
281
|
+
url=url,
|
|
282
|
+
metadata=metadata,
|
|
283
|
+
file=file,
|
|
284
|
+
text_content=text_content,
|
|
285
|
+
reader_id=reader_id,
|
|
286
|
+
chunker=chunker,
|
|
287
|
+
chunk_size=chunk_size,
|
|
288
|
+
chunk_overlap=chunk_overlap,
|
|
289
|
+
db_id=db_id,
|
|
290
|
+
**kwargs,
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
async def update_content(
|
|
294
|
+
self,
|
|
295
|
+
content_id: str,
|
|
296
|
+
name: Optional[str] = None,
|
|
297
|
+
description: Optional[str] = None,
|
|
298
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
299
|
+
reader_id: Optional[str] = None,
|
|
300
|
+
db_id: Optional[str] = None,
|
|
301
|
+
**kwargs: Any,
|
|
302
|
+
) -> "ContentResponseSchema":
|
|
303
|
+
return await self.client.update_knowledge_content(
|
|
304
|
+
content_id=content_id,
|
|
305
|
+
name=name,
|
|
306
|
+
description=description,
|
|
307
|
+
metadata=metadata,
|
|
308
|
+
reader_id=reader_id,
|
|
309
|
+
db_id=db_id,
|
|
310
|
+
**kwargs,
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
async def get_content(
|
|
314
|
+
self,
|
|
315
|
+
limit: Optional[int] = None,
|
|
316
|
+
page: Optional[int] = None,
|
|
317
|
+
sort_by: Optional[str] = None,
|
|
318
|
+
sort_order: Optional[str] = None,
|
|
319
|
+
db_id: Optional[str] = None,
|
|
320
|
+
**kwargs: Any,
|
|
321
|
+
) -> "PaginatedResponse[ContentResponseSchema]":
|
|
322
|
+
return await self.client.list_knowledge_content(
|
|
323
|
+
limit=limit, page=page, sort_by=sort_by, sort_order=sort_order, db_id=db_id, **kwargs
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
async def get_content_by_id(
|
|
327
|
+
self, content_id: str, db_id: Optional[str] = None, **kwargs: Any
|
|
328
|
+
) -> "ContentResponseSchema":
|
|
329
|
+
return await self.client.get_knowledge_content(content_id=content_id, db_id=db_id, **kwargs)
|
|
330
|
+
|
|
331
|
+
async def delete_content_by_id(self, content_id: str, db_id: Optional[str] = None, **kwargs: Any) -> None:
|
|
332
|
+
await self.client.delete_knowledge_content(content_id=content_id, db_id=db_id, **kwargs)
|
|
333
|
+
|
|
334
|
+
async def delete_all_content(self, db_id: Optional[str] = None, **kwargs: Any) -> None:
|
|
335
|
+
await self.client.delete_all_knowledge_content(db_id=db_id, **kwargs)
|
|
336
|
+
|
|
337
|
+
async def get_content_status(
|
|
338
|
+
self, content_id: str, db_id: Optional[str] = None, **kwargs: Any
|
|
339
|
+
) -> "ContentStatusResponse":
|
|
340
|
+
return await self.client.get_knowledge_content_status(content_id=content_id, db_id=db_id, **kwargs)
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
@dataclass
|
|
344
|
+
class BaseRemote:
|
|
345
|
+
# Private cache for OS config with TTL: (config, timestamp)
|
|
346
|
+
_cached_config: Optional[Tuple["ConfigResponse", float]] = field(default=None, init=False, repr=False)
|
|
347
|
+
|
|
348
|
+
def __init__(
|
|
349
|
+
self,
|
|
350
|
+
base_url: str,
|
|
351
|
+
timeout: float = 60.0,
|
|
352
|
+
config_ttl: float = 300.0,
|
|
353
|
+
):
|
|
354
|
+
"""Initialize BaseRemote for remote execution.
|
|
355
|
+
|
|
356
|
+
For local execution, provide agent/team/workflow instances.
|
|
357
|
+
For remote execution, provide base_url.
|
|
358
|
+
|
|
359
|
+
Args:
|
|
360
|
+
base_url: Base URL for remote instance (e.g., "http://localhost:7777")
|
|
361
|
+
timeout: Request timeout in seconds (default: 60)
|
|
362
|
+
config_ttl: Time-to-live for cached config in seconds (default: 300)
|
|
363
|
+
"""
|
|
364
|
+
self.base_url = base_url.rstrip("/")
|
|
365
|
+
self.timeout: float = timeout
|
|
366
|
+
self.config_ttl: float = config_ttl
|
|
367
|
+
self._cached_config = None
|
|
368
|
+
|
|
369
|
+
self.client = self.get_client()
|
|
370
|
+
|
|
371
|
+
def get_client(self) -> "AgentOSClient":
|
|
372
|
+
"""Get an AgentOSClient for fetching remote configuration.
|
|
373
|
+
|
|
374
|
+
This is used internally by AgentOS to fetch configuration from remote
|
|
375
|
+
AgentOS instances when this runner represents a remote resource.
|
|
376
|
+
|
|
377
|
+
Returns:
|
|
378
|
+
AgentOSClient: Client configured for this remote resource's base URL
|
|
379
|
+
"""
|
|
380
|
+
from agno.client import AgentOSClient
|
|
381
|
+
|
|
382
|
+
return AgentOSClient(
|
|
383
|
+
base_url=self.base_url,
|
|
384
|
+
timeout=self.timeout,
|
|
385
|
+
)
|
|
386
|
+
|
|
387
|
+
@property
|
|
388
|
+
def _config(self) -> "ConfigResponse":
|
|
389
|
+
"""Get the OS config from remote, cached with TTL."""
|
|
390
|
+
from agno.os.schema import ConfigResponse
|
|
391
|
+
|
|
392
|
+
current_time = time.time()
|
|
393
|
+
|
|
394
|
+
# Check if cache is valid
|
|
395
|
+
if self._cached_config is not None:
|
|
396
|
+
config, cached_at = self._cached_config
|
|
397
|
+
if current_time - cached_at < self.config_ttl:
|
|
398
|
+
return config
|
|
399
|
+
|
|
400
|
+
# Fetch fresh config
|
|
401
|
+
config: ConfigResponse = self.client.get_config() # type: ignore
|
|
402
|
+
self._cached_config = (config, current_time)
|
|
403
|
+
return config
|
|
404
|
+
|
|
405
|
+
def refresh_os_config(self) -> "ConfigResponse":
|
|
406
|
+
"""Force refresh the cached OS config."""
|
|
407
|
+
from agno.os.schema import ConfigResponse
|
|
408
|
+
|
|
409
|
+
config: ConfigResponse = self.client.get_config()
|
|
410
|
+
self._cached_config = (config, time.time())
|
|
411
|
+
return config
|
|
412
|
+
|
|
413
|
+
def _get_headers(self, auth_token: Optional[str] = None) -> Dict[str, str]:
|
|
414
|
+
"""Get headers for HTTP requests.
|
|
415
|
+
|
|
416
|
+
Args:
|
|
417
|
+
auth_token: Optional JWT token for authentication
|
|
418
|
+
|
|
419
|
+
Returns:
|
|
420
|
+
Dict[str, str]: Headers including Content-Type and optional Authorization
|
|
421
|
+
"""
|
|
422
|
+
headers = {"Content-Type": "application/x-www-form-urlencoded"}
|
|
423
|
+
if auth_token:
|
|
424
|
+
headers["Authorization"] = f"Bearer {auth_token}"
|
|
425
|
+
return headers
|
|
426
|
+
|
|
427
|
+
def _get_auth_headers(self, auth_token: Optional[str] = None) -> Optional[Dict[str, str]]:
|
|
428
|
+
"""Get Authorization headers for HTTP requests.
|
|
429
|
+
|
|
430
|
+
Args:
|
|
431
|
+
auth_token: Optional JWT token for authentication
|
|
432
|
+
|
|
433
|
+
Returns:
|
|
434
|
+
Dict[str, str] with Authorization header if auth_token is provided, None otherwise
|
|
435
|
+
"""
|
|
436
|
+
if auth_token:
|
|
437
|
+
return {"Authorization": f"Bearer {auth_token}"}
|
|
438
|
+
return None
|
|
439
|
+
|
|
440
|
+
@abstractmethod
|
|
441
|
+
def arun( # type: ignore
|
|
442
|
+
self,
|
|
443
|
+
input: Union[str, List, Dict, Message, BaseModel, List[Message]],
|
|
444
|
+
*,
|
|
445
|
+
stream: Optional[bool] = None,
|
|
446
|
+
user_id: Optional[str] = None,
|
|
447
|
+
session_id: Optional[str] = None,
|
|
448
|
+
session_state: Optional[Dict[str, Any]] = None,
|
|
449
|
+
audio: Optional[Sequence[Audio]] = None,
|
|
450
|
+
images: Optional[Sequence[Image]] = None,
|
|
451
|
+
videos: Optional[Sequence[Video]] = None,
|
|
452
|
+
files: Optional[Sequence[File]] = None,
|
|
453
|
+
stream_events: Optional[bool] = None,
|
|
454
|
+
retries: Optional[int] = None,
|
|
455
|
+
knowledge_filters: Optional[Dict[str, Any]] = None,
|
|
456
|
+
add_history_to_context: Optional[bool] = None,
|
|
457
|
+
add_dependencies_to_context: Optional[bool] = None,
|
|
458
|
+
add_session_state_to_context: Optional[bool] = None,
|
|
459
|
+
dependencies: Optional[Dict[str, Any]] = None,
|
|
460
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
461
|
+
auth_token: Optional[str] = None,
|
|
462
|
+
**kwargs: Any,
|
|
463
|
+
) -> Union[
|
|
464
|
+
RunOutput,
|
|
465
|
+
TeamRunOutput,
|
|
466
|
+
WorkflowRunOutput,
|
|
467
|
+
AsyncIterator[Union[RunOutputEvent, TeamRunOutputEvent, WorkflowRunOutputEvent]],
|
|
468
|
+
]:
|
|
469
|
+
raise NotImplementedError("arun method must be implemented by the subclass")
|
|
470
|
+
|
|
471
|
+
@abstractmethod
|
|
472
|
+
async def acontinue_run( # type: ignore
|
|
473
|
+
self,
|
|
474
|
+
run_id: str,
|
|
475
|
+
stream: Optional[bool] = None,
|
|
476
|
+
updated_tools: Optional[List[ToolExecution]] = None,
|
|
477
|
+
user_id: Optional[str] = None,
|
|
478
|
+
session_id: Optional[str] = None,
|
|
479
|
+
) -> Union[RunOutput, TeamRunOutput, WorkflowRunOutput]:
|
|
480
|
+
raise NotImplementedError("acontinue_run method must be implemented by the subclass")
|
|
481
|
+
|
|
482
|
+
@abstractmethod
|
|
483
|
+
async def cancel_run(self, run_id: str) -> bool:
|
|
484
|
+
raise NotImplementedError("cancel_run method must be implemented by the subclass")
|
agno/run/workflow.py
CHANGED
agno/team/__init__.py
CHANGED
|
@@ -15,10 +15,12 @@ from agno.run.team import (
|
|
|
15
15
|
ToolCallCompletedEvent,
|
|
16
16
|
ToolCallStartedEvent,
|
|
17
17
|
)
|
|
18
|
+
from agno.team.remote import RemoteTeam
|
|
18
19
|
from agno.team.team import Team
|
|
19
20
|
|
|
20
21
|
__all__ = [
|
|
21
22
|
"Team",
|
|
23
|
+
"RemoteTeam",
|
|
22
24
|
"TeamRunOutput",
|
|
23
25
|
"TeamRunOutputEvent",
|
|
24
26
|
"TeamRunEvent",
|