cortex-agent-sdk 0.2.1__tar.gz → 0.3.1__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.
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.1}/PKG-INFO +44 -17
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.1}/README.md +38 -12
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.1}/pyproject.toml +8 -6
- cortex_agent_sdk-0.3.1/src/cortex_agent_sdk/capabilities.py +62 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.1}/.gitignore +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.1}/LICENSE +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.1}/src/cortex_agent_sdk/__init__.py +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.1}/src/cortex_agent_sdk/errores/__init__.py +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.1}/src/cortex_agent_sdk/errores/catalogo.py +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.1}/src/cortex_agent_sdk/errores/excepcion.py +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.1}/src/cortex_agent_sdk/py.typed +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.1}/src/cortex_agent_sdk/redis/__init__.py +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.1}/src/cortex_agent_sdk/redis/scripts.py +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.1}/src/cortex_agent_sdk/redis/store.py +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.1}/src/cortex_agent_sdk/sessions/__init__.py +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.1}/src/cortex_agent_sdk/sessions/codec.py +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.1}/src/cortex_agent_sdk/sessions/memory.py +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.1}/src/cortex_agent_sdk/sessions/models.py +0 -0
- {cortex_agent_sdk-0.2.1 → cortex_agent_sdk-0.3.1}/src/cortex_agent_sdk/sessions/store.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cortex-agent-sdk
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary: Sesiones
|
|
3
|
+
Version: 0.3.1
|
|
4
|
+
Summary: Sesiones y capacidades puntuales para agentes multiprovider con Pydantic AI
|
|
5
5
|
Project-URL: Repository, https://github.com/epok200/cortex_agent_sdk
|
|
6
6
|
Project-URL: Issues, https://github.com/epok200/cortex_agent_sdk/issues
|
|
7
7
|
Author: EPOK
|
|
@@ -16,53 +16,60 @@ Classifier: Programming Language :: Python :: 3
|
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.13
|
|
17
17
|
Classifier: Typing :: Typed
|
|
18
18
|
Requires-Python: >=3.13
|
|
19
|
-
Requires-Dist: pydantic-ai-slim
|
|
20
|
-
Provides-Extra:
|
|
21
|
-
Requires-Dist:
|
|
19
|
+
Requires-Dist: pydantic-ai-slim<3,>=2.27
|
|
20
|
+
Provides-Extra: google
|
|
21
|
+
Requires-Dist: pydantic-ai-slim[google]<3,>=2.27; extra == 'google'
|
|
22
22
|
Provides-Extra: openai
|
|
23
|
+
Requires-Dist: pydantic-ai-slim[openai]<3,>=2.27; extra == 'openai'
|
|
23
24
|
Provides-Extra: redis
|
|
24
25
|
Requires-Dist: redis>=8.1.0; extra == 'redis'
|
|
25
26
|
Description-Content-Type: text/markdown
|
|
26
27
|
|
|
27
28
|
# Cortex Agent SDK
|
|
28
29
|
|
|
29
|
-
Cortex agrega sesiones Memory y Redis
|
|
30
|
-
Pydantic AI.
|
|
30
|
+
Cortex agrega sesiones Memory y Redis, junto con capacidades puntuales que Pydantic AI no incluye,
|
|
31
|
+
a agentes multiprovider construidos directamente con Pydantic AI.
|
|
31
32
|
|
|
32
33
|
No implementa otro loop, otra capa de tools ni otra API de agentes. Pydantic AI conserva el control
|
|
33
34
|
de providers, modelos, tools, tipado, `RunContext`, hooks, límites, approvals, outputs, usage e
|
|
34
|
-
historial. Cortex
|
|
35
|
-
|
|
35
|
+
historial. Cortex aporta persistencia conversacional con un turno activo por sesión y capacidades
|
|
36
|
+
opcionales construidas sobre sus hooks públicos.
|
|
36
37
|
|
|
37
38
|
> Cortex Agent SDK está en alfa. La API puede cambiar antes de la versión `1.0.0`.
|
|
38
39
|
|
|
39
40
|
## Requisitos
|
|
40
41
|
|
|
41
42
|
- Python `>=3.13`.
|
|
42
|
-
- Pydantic AI `>=2.27,<3
|
|
43
|
+
- Pydantic AI `>=2.27,<3`.
|
|
43
44
|
|
|
44
45
|
## Instalación
|
|
45
46
|
|
|
46
|
-
|
|
47
|
+
Solo sesiones en memoria y capabilities:
|
|
47
48
|
|
|
48
49
|
```bash
|
|
49
50
|
uv add cortex-agent-sdk
|
|
50
51
|
```
|
|
51
52
|
|
|
52
|
-
|
|
53
|
+
OpenAI y sesiones en memoria:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
uv add "cortex-agent-sdk[openai]"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
OpenAI y Redis:
|
|
53
60
|
|
|
54
61
|
```bash
|
|
55
|
-
uv add "cortex-agent-sdk[redis]"
|
|
62
|
+
uv add "cortex-agent-sdk[openai,redis]"
|
|
56
63
|
```
|
|
57
64
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
los necesite. Cortex no implementa adapters paralelos.
|
|
65
|
+
Google se instala con el extra `google`. Cada producto elige únicamente sus providers. Cortex no
|
|
66
|
+
implementa adapters paralelos ni ofrece un extra que los instale todos.
|
|
61
67
|
|
|
62
68
|
## Uso
|
|
63
69
|
|
|
64
70
|
El agente es el `Agent` nativo de Pydantic AI. El store entrega el historial bajo exclusión y lo
|
|
65
71
|
guarda cuando `session.replace(...)` marca un resultado completo.
|
|
72
|
+
El siguiente ejemplo requiere el extra `openai`.
|
|
66
73
|
|
|
67
74
|
```python
|
|
68
75
|
import asyncio
|
|
@@ -138,6 +145,25 @@ agent = Agent(model)
|
|
|
138
145
|
|
|
139
146
|
El context manager de `Agent` administra el transporte del provider.
|
|
140
147
|
|
|
148
|
+
## Fallback del resultado de una tool
|
|
149
|
+
|
|
150
|
+
Pydantic AI reintenta cuando un modelo termina sin texto. Para tools cuyo resultado ya es una
|
|
151
|
+
respuesta completa, Cortex puede reutilizar el último resultado exitoso del mismo run:
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
from pydantic_ai import Agent
|
|
155
|
+
|
|
156
|
+
from cortex_agent_sdk.capabilities import last_tool_result_fallback
|
|
157
|
+
|
|
158
|
+
agent = Agent(
|
|
159
|
+
"openai-responses:gpt-5.6-luna",
|
|
160
|
+
capabilities=[last_tool_result_fallback({"confirmar_agenda"})],
|
|
161
|
+
)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
La aplicación conserva la decisión sobre las tools elegibles. La capacidad no usa resultados
|
|
165
|
+
fallidos, vacíos ni pertenecientes a otro run, y no reemplaza texto o nuevas llamadas del modelo.
|
|
166
|
+
|
|
141
167
|
## Migración desde el runtime anterior
|
|
142
168
|
|
|
143
169
|
| Antes | Ahora |
|
|
@@ -151,7 +177,7 @@ El context manager de `Agent` administra el transporte del provider.
|
|
|
151
177
|
| `AgentHooks` | `pydantic_ai.capabilities.Hooks` |
|
|
152
178
|
| `turn_finished` | `Hooks(after_run=...)` |
|
|
153
179
|
| `history_transform` | `Hooks(before_model_request=...)` |
|
|
154
|
-
| `fallback_answer` |
|
|
180
|
+
| `fallback_answer` | `last_tool_result_fallback(...)` opcional |
|
|
155
181
|
| `AgentOptions` | `UsageLimits`, settings del modelo y argumentos de `Agent` |
|
|
156
182
|
| `AgentResult.text` | `AgentRunResult.output` |
|
|
157
183
|
| `SessionStore.acquire` | `SessionStore.turn` + `Session.replace` |
|
|
@@ -166,6 +192,7 @@ Pydantic AI.
|
|
|
166
192
|
- `cortex_agent_sdk.sessions.SessionStore`
|
|
167
193
|
- `cortex_agent_sdk.sessions.MemorySessionStore`
|
|
168
194
|
- `cortex_agent_sdk.redis.RedisSessionStore`
|
|
195
|
+
- `cortex_agent_sdk.capabilities.last_tool_result_fallback`
|
|
169
196
|
- `cortex_agent_sdk.errores.AppError`
|
|
170
197
|
- `cortex_agent_sdk.errores.CodigoError`
|
|
171
198
|
- `cortex_agent_sdk.errores.Severidad`
|
|
@@ -1,42 +1,48 @@
|
|
|
1
1
|
# Cortex Agent SDK
|
|
2
2
|
|
|
3
|
-
Cortex agrega sesiones Memory y Redis
|
|
4
|
-
Pydantic AI.
|
|
3
|
+
Cortex agrega sesiones Memory y Redis, junto con capacidades puntuales que Pydantic AI no incluye,
|
|
4
|
+
a agentes multiprovider construidos directamente con Pydantic AI.
|
|
5
5
|
|
|
6
6
|
No implementa otro loop, otra capa de tools ni otra API de agentes. Pydantic AI conserva el control
|
|
7
7
|
de providers, modelos, tools, tipado, `RunContext`, hooks, límites, approvals, outputs, usage e
|
|
8
|
-
historial. Cortex
|
|
9
|
-
|
|
8
|
+
historial. Cortex aporta persistencia conversacional con un turno activo por sesión y capacidades
|
|
9
|
+
opcionales construidas sobre sus hooks públicos.
|
|
10
10
|
|
|
11
11
|
> Cortex Agent SDK está en alfa. La API puede cambiar antes de la versión `1.0.0`.
|
|
12
12
|
|
|
13
13
|
## Requisitos
|
|
14
14
|
|
|
15
15
|
- Python `>=3.13`.
|
|
16
|
-
- Pydantic AI `>=2.27,<3
|
|
16
|
+
- Pydantic AI `>=2.27,<3`.
|
|
17
17
|
|
|
18
18
|
## Instalación
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
Solo sesiones en memoria y capabilities:
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
23
|
uv add cortex-agent-sdk
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
OpenAI y sesiones en memoria:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
uv add "cortex-agent-sdk[openai]"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
OpenAI y Redis:
|
|
27
33
|
|
|
28
34
|
```bash
|
|
29
|
-
uv add "cortex-agent-sdk[redis]"
|
|
35
|
+
uv add "cortex-agent-sdk[openai,redis]"
|
|
30
36
|
```
|
|
31
37
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
los necesite. Cortex no implementa adapters paralelos.
|
|
38
|
+
Google se instala con el extra `google`. Cada producto elige únicamente sus providers. Cortex no
|
|
39
|
+
implementa adapters paralelos ni ofrece un extra que los instale todos.
|
|
35
40
|
|
|
36
41
|
## Uso
|
|
37
42
|
|
|
38
43
|
El agente es el `Agent` nativo de Pydantic AI. El store entrega el historial bajo exclusión y lo
|
|
39
44
|
guarda cuando `session.replace(...)` marca un resultado completo.
|
|
45
|
+
El siguiente ejemplo requiere el extra `openai`.
|
|
40
46
|
|
|
41
47
|
```python
|
|
42
48
|
import asyncio
|
|
@@ -112,6 +118,25 @@ agent = Agent(model)
|
|
|
112
118
|
|
|
113
119
|
El context manager de `Agent` administra el transporte del provider.
|
|
114
120
|
|
|
121
|
+
## Fallback del resultado de una tool
|
|
122
|
+
|
|
123
|
+
Pydantic AI reintenta cuando un modelo termina sin texto. Para tools cuyo resultado ya es una
|
|
124
|
+
respuesta completa, Cortex puede reutilizar el último resultado exitoso del mismo run:
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
from pydantic_ai import Agent
|
|
128
|
+
|
|
129
|
+
from cortex_agent_sdk.capabilities import last_tool_result_fallback
|
|
130
|
+
|
|
131
|
+
agent = Agent(
|
|
132
|
+
"openai-responses:gpt-5.6-luna",
|
|
133
|
+
capabilities=[last_tool_result_fallback({"confirmar_agenda"})],
|
|
134
|
+
)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
La aplicación conserva la decisión sobre las tools elegibles. La capacidad no usa resultados
|
|
138
|
+
fallidos, vacíos ni pertenecientes a otro run, y no reemplaza texto o nuevas llamadas del modelo.
|
|
139
|
+
|
|
115
140
|
## Migración desde el runtime anterior
|
|
116
141
|
|
|
117
142
|
| Antes | Ahora |
|
|
@@ -125,7 +150,7 @@ El context manager de `Agent` administra el transporte del provider.
|
|
|
125
150
|
| `AgentHooks` | `pydantic_ai.capabilities.Hooks` |
|
|
126
151
|
| `turn_finished` | `Hooks(after_run=...)` |
|
|
127
152
|
| `history_transform` | `Hooks(before_model_request=...)` |
|
|
128
|
-
| `fallback_answer` |
|
|
153
|
+
| `fallback_answer` | `last_tool_result_fallback(...)` opcional |
|
|
129
154
|
| `AgentOptions` | `UsageLimits`, settings del modelo y argumentos de `Agent` |
|
|
130
155
|
| `AgentResult.text` | `AgentRunResult.output` |
|
|
131
156
|
| `SessionStore.acquire` | `SessionStore.turn` + `Session.replace` |
|
|
@@ -140,6 +165,7 @@ Pydantic AI.
|
|
|
140
165
|
- `cortex_agent_sdk.sessions.SessionStore`
|
|
141
166
|
- `cortex_agent_sdk.sessions.MemorySessionStore`
|
|
142
167
|
- `cortex_agent_sdk.redis.RedisSessionStore`
|
|
168
|
+
- `cortex_agent_sdk.capabilities.last_tool_result_fallback`
|
|
143
169
|
- `cortex_agent_sdk.errores.AppError`
|
|
144
170
|
- `cortex_agent_sdk.errores.CodigoError`
|
|
145
171
|
- `cortex_agent_sdk.errores.Severidad`
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "cortex-agent-sdk"
|
|
3
|
-
version = "0.
|
|
4
|
-
description = "Sesiones
|
|
3
|
+
version = "0.3.1"
|
|
4
|
+
description = "Sesiones y capacidades puntuales para agentes multiprovider con Pydantic AI"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "Apache-2.0"
|
|
7
7
|
requires-python = ">=3.13"
|
|
@@ -17,7 +17,7 @@ classifiers = [
|
|
|
17
17
|
"Typing :: Typed",
|
|
18
18
|
]
|
|
19
19
|
dependencies = [
|
|
20
|
-
"pydantic-ai-slim
|
|
20
|
+
"pydantic-ai-slim>=2.27,<3",
|
|
21
21
|
]
|
|
22
22
|
|
|
23
23
|
[project.urls]
|
|
@@ -25,9 +25,11 @@ Repository = "https://github.com/epok200/cortex_agent_sdk"
|
|
|
25
25
|
Issues = "https://github.com/epok200/cortex_agent_sdk/issues"
|
|
26
26
|
|
|
27
27
|
[project.optional-dependencies]
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
google = [
|
|
29
|
+
"pydantic-ai-slim[google]>=2.27,<3",
|
|
30
|
+
]
|
|
31
|
+
openai = [
|
|
32
|
+
"pydantic-ai-slim[openai]>=2.27,<3",
|
|
31
33
|
]
|
|
32
34
|
redis = [
|
|
33
35
|
"redis>=8.1.0",
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""Capacidades opcionales para agentes Pydantic AI."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Collection
|
|
4
|
+
from dataclasses import replace
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from pydantic_ai import ModelResponse, RunContext, TextPart
|
|
8
|
+
from pydantic_ai.capabilities.hooks import Hooks
|
|
9
|
+
from pydantic_ai.messages import ModelRequest, ToolReturnPart
|
|
10
|
+
from pydantic_ai.models import ModelRequestContext
|
|
11
|
+
|
|
12
|
+
__all__ = ["last_tool_result_fallback"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def last_tool_result_fallback(tool_names: str | Collection[str]) -> Hooks[Any]:
|
|
16
|
+
"""Usa el último resultado elegible si el modelo termina sin texto."""
|
|
17
|
+
if isinstance(tool_names, str):
|
|
18
|
+
eligible_tools = frozenset((tool_names,))
|
|
19
|
+
else:
|
|
20
|
+
eligible_tools = frozenset(tool_names)
|
|
21
|
+
|
|
22
|
+
def use_last_tool_result(
|
|
23
|
+
ctx: RunContext[Any],
|
|
24
|
+
*,
|
|
25
|
+
request_context: ModelRequestContext,
|
|
26
|
+
response: ModelResponse,
|
|
27
|
+
) -> ModelResponse:
|
|
28
|
+
if response.finish_reason not in {None, "stop"}:
|
|
29
|
+
return response
|
|
30
|
+
if response.text and response.text.strip():
|
|
31
|
+
return response
|
|
32
|
+
if response.tool_calls:
|
|
33
|
+
return response
|
|
34
|
+
|
|
35
|
+
result = _last_tool_result(request_context, ctx.run_id, eligible_tools)
|
|
36
|
+
if result is None:
|
|
37
|
+
return response
|
|
38
|
+
return replace(response, parts=[*response.parts, TextPart(result)])
|
|
39
|
+
|
|
40
|
+
return Hooks(after_model_request=use_last_tool_result)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _last_tool_result(
|
|
44
|
+
request_context: ModelRequestContext,
|
|
45
|
+
run_id: str | None,
|
|
46
|
+
tool_names: Collection[str],
|
|
47
|
+
) -> str | None:
|
|
48
|
+
if run_id is None:
|
|
49
|
+
return None
|
|
50
|
+
for message in reversed(request_context.messages):
|
|
51
|
+
if not isinstance(message, ModelRequest) or message.run_id != run_id:
|
|
52
|
+
continue
|
|
53
|
+
for part in reversed(message.parts):
|
|
54
|
+
if (
|
|
55
|
+
isinstance(part, ToolReturnPart)
|
|
56
|
+
and part.outcome == "success"
|
|
57
|
+
and part.tool_name in tool_names
|
|
58
|
+
and isinstance(part.content, str)
|
|
59
|
+
and part.content.strip()
|
|
60
|
+
):
|
|
61
|
+
return part.content
|
|
62
|
+
return None
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|