cortex-agent-sdk 0.2.0__tar.gz → 0.3.0__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.0 → cortex_agent_sdk-0.3.0}/PKG-INFO +35 -20
- {cortex_agent_sdk-0.2.0 → cortex_agent_sdk-0.3.0}/README.md +32 -13
- {cortex_agent_sdk-0.2.0 → cortex_agent_sdk-0.3.0}/pyproject.toml +4 -11
- cortex_agent_sdk-0.3.0/src/cortex_agent_sdk/capabilities.py +62 -0
- {cortex_agent_sdk-0.2.0 → cortex_agent_sdk-0.3.0}/.gitignore +0 -0
- {cortex_agent_sdk-0.2.0 → cortex_agent_sdk-0.3.0}/LICENSE +0 -0
- {cortex_agent_sdk-0.2.0 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/__init__.py +0 -0
- {cortex_agent_sdk-0.2.0 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/errores/__init__.py +0 -0
- {cortex_agent_sdk-0.2.0 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/errores/catalogo.py +0 -0
- {cortex_agent_sdk-0.2.0 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/errores/excepcion.py +0 -0
- {cortex_agent_sdk-0.2.0 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/py.typed +0 -0
- {cortex_agent_sdk-0.2.0 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/redis/__init__.py +0 -0
- {cortex_agent_sdk-0.2.0 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/redis/scripts.py +0 -0
- {cortex_agent_sdk-0.2.0 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/redis/store.py +0 -0
- {cortex_agent_sdk-0.2.0 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/sessions/__init__.py +0 -0
- {cortex_agent_sdk-0.2.0 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/sessions/codec.py +0 -0
- {cortex_agent_sdk-0.2.0 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/sessions/memory.py +0 -0
- {cortex_agent_sdk-0.2.0 → cortex_agent_sdk-0.3.0}/src/cortex_agent_sdk/sessions/models.py +0 -0
- {cortex_agent_sdk-0.2.0 → cortex_agent_sdk-0.3.0}/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.0
|
|
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,51 +16,46 @@ 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<3,>=2.27
|
|
20
|
-
Provides-Extra: all
|
|
21
|
-
Requires-Dist: pydantic-ai-slim[openai]<3,>=2.27; extra == 'all'
|
|
22
|
-
Requires-Dist: redis>=8.1.0; extra == 'all'
|
|
19
|
+
Requires-Dist: pydantic-ai-slim[google,openai]<3,>=2.27
|
|
23
20
|
Provides-Extra: openai
|
|
24
|
-
Requires-Dist: pydantic-ai-slim[openai]<3,>=2.27; extra == 'openai'
|
|
25
21
|
Provides-Extra: redis
|
|
26
22
|
Requires-Dist: redis>=8.1.0; extra == 'redis'
|
|
27
23
|
Description-Content-Type: text/markdown
|
|
28
24
|
|
|
29
25
|
# Cortex Agent SDK
|
|
30
26
|
|
|
31
|
-
Cortex agrega sesiones Memory y Redis
|
|
27
|
+
Cortex agrega sesiones Memory y Redis, junto con capacidades puntuales que Pydantic AI no incluye,
|
|
28
|
+
a agentes multiprovider construidos directamente con Pydantic AI.
|
|
32
29
|
|
|
33
30
|
No implementa otro loop, otra capa de tools ni otra API de agentes. Pydantic AI conserva el control
|
|
34
31
|
de providers, modelos, tools, tipado, `RunContext`, hooks, límites, approvals, outputs, usage e
|
|
35
|
-
historial. Cortex
|
|
36
|
-
|
|
32
|
+
historial. Cortex aporta persistencia conversacional con un turno activo por sesión y capacidades
|
|
33
|
+
opcionales construidas sobre sus hooks públicos.
|
|
37
34
|
|
|
38
35
|
> Cortex Agent SDK está en alfa. La API puede cambiar antes de la versión `1.0.0`.
|
|
39
36
|
|
|
40
37
|
## Requisitos
|
|
41
38
|
|
|
42
39
|
- Python `>=3.13`.
|
|
43
|
-
- Pydantic AI `>=2.27,<3`,
|
|
40
|
+
- Pydantic AI `>=2.27,<3`, con Google y OpenAI instalados por Cortex.
|
|
44
41
|
|
|
45
42
|
## Instalación
|
|
46
43
|
|
|
47
|
-
|
|
44
|
+
Google, OpenAI y sesiones en memoria:
|
|
48
45
|
|
|
49
46
|
```bash
|
|
50
47
|
uv add cortex-agent-sdk
|
|
51
48
|
```
|
|
52
49
|
|
|
53
|
-
OpenAI
|
|
50
|
+
Google, OpenAI y Redis:
|
|
54
51
|
|
|
55
52
|
```bash
|
|
56
|
-
uv add "cortex-agent-sdk[
|
|
53
|
+
uv add "cortex-agent-sdk[redis]"
|
|
57
54
|
```
|
|
58
55
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
uv add "cortex-agent-sdk[openai,redis]"
|
|
63
|
-
```
|
|
56
|
+
La instalación base incluye Google y OpenAI, además de los endpoints compatibles con OpenAI. Otros
|
|
57
|
+
providers pueden agregarse desde los extras oficiales de Pydantic AI cuando un producto realmente
|
|
58
|
+
los necesite. Cortex no implementa adapters paralelos.
|
|
64
59
|
|
|
65
60
|
## Uso
|
|
66
61
|
|
|
@@ -141,6 +136,25 @@ agent = Agent(model)
|
|
|
141
136
|
|
|
142
137
|
El context manager de `Agent` administra el transporte del provider.
|
|
143
138
|
|
|
139
|
+
## Fallback del resultado de una tool
|
|
140
|
+
|
|
141
|
+
Pydantic AI reintenta cuando un modelo termina sin texto. Para tools cuyo resultado ya es una
|
|
142
|
+
respuesta completa, Cortex puede reutilizar el último resultado exitoso del mismo run:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
from pydantic_ai import Agent
|
|
146
|
+
|
|
147
|
+
from cortex_agent_sdk.capabilities import last_tool_result_fallback
|
|
148
|
+
|
|
149
|
+
agent = Agent(
|
|
150
|
+
"openai-responses:gpt-5.6-luna",
|
|
151
|
+
capabilities=[last_tool_result_fallback({"confirmar_agenda"})],
|
|
152
|
+
)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
La aplicación conserva la decisión sobre las tools elegibles. La capacidad no usa resultados
|
|
156
|
+
fallidos, vacíos ni pertenecientes a otro run, y no reemplaza texto o nuevas llamadas del modelo.
|
|
157
|
+
|
|
144
158
|
## Migración desde el runtime anterior
|
|
145
159
|
|
|
146
160
|
| Antes | Ahora |
|
|
@@ -154,7 +168,7 @@ El context manager de `Agent` administra el transporte del provider.
|
|
|
154
168
|
| `AgentHooks` | `pydantic_ai.capabilities.Hooks` |
|
|
155
169
|
| `turn_finished` | `Hooks(after_run=...)` |
|
|
156
170
|
| `history_transform` | `Hooks(before_model_request=...)` |
|
|
157
|
-
| `fallback_answer` |
|
|
171
|
+
| `fallback_answer` | `last_tool_result_fallback(...)` opcional |
|
|
158
172
|
| `AgentOptions` | `UsageLimits`, settings del modelo y argumentos de `Agent` |
|
|
159
173
|
| `AgentResult.text` | `AgentRunResult.output` |
|
|
160
174
|
| `SessionStore.acquire` | `SessionStore.turn` + `Session.replace` |
|
|
@@ -169,6 +183,7 @@ Pydantic AI.
|
|
|
169
183
|
- `cortex_agent_sdk.sessions.SessionStore`
|
|
170
184
|
- `cortex_agent_sdk.sessions.MemorySessionStore`
|
|
171
185
|
- `cortex_agent_sdk.redis.RedisSessionStore`
|
|
186
|
+
- `cortex_agent_sdk.capabilities.last_tool_result_fallback`
|
|
172
187
|
- `cortex_agent_sdk.errores.AppError`
|
|
173
188
|
- `cortex_agent_sdk.errores.CodigoError`
|
|
174
189
|
- `cortex_agent_sdk.errores.Severidad`
|
|
@@ -1,38 +1,37 @@
|
|
|
1
1
|
# Cortex Agent SDK
|
|
2
2
|
|
|
3
|
-
Cortex agrega sesiones Memory y Redis
|
|
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.
|
|
4
5
|
|
|
5
6
|
No implementa otro loop, otra capa de tools ni otra API de agentes. Pydantic AI conserva el control
|
|
6
7
|
de providers, modelos, tools, tipado, `RunContext`, hooks, límites, approvals, outputs, usage e
|
|
7
|
-
historial. Cortex
|
|
8
|
-
|
|
8
|
+
historial. Cortex aporta persistencia conversacional con un turno activo por sesión y capacidades
|
|
9
|
+
opcionales construidas sobre sus hooks públicos.
|
|
9
10
|
|
|
10
11
|
> Cortex Agent SDK está en alfa. La API puede cambiar antes de la versión `1.0.0`.
|
|
11
12
|
|
|
12
13
|
## Requisitos
|
|
13
14
|
|
|
14
15
|
- Python `>=3.13`.
|
|
15
|
-
- Pydantic AI `>=2.27,<3`,
|
|
16
|
+
- Pydantic AI `>=2.27,<3`, con Google y OpenAI instalados por Cortex.
|
|
16
17
|
|
|
17
18
|
## Instalación
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
Google, OpenAI y sesiones en memoria:
|
|
20
21
|
|
|
21
22
|
```bash
|
|
22
23
|
uv add cortex-agent-sdk
|
|
23
24
|
```
|
|
24
25
|
|
|
25
|
-
OpenAI
|
|
26
|
+
Google, OpenAI y Redis:
|
|
26
27
|
|
|
27
28
|
```bash
|
|
28
|
-
uv add "cortex-agent-sdk[
|
|
29
|
+
uv add "cortex-agent-sdk[redis]"
|
|
29
30
|
```
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
uv add "cortex-agent-sdk[openai,redis]"
|
|
35
|
-
```
|
|
32
|
+
La instalación base incluye Google y OpenAI, además de los endpoints compatibles con OpenAI. Otros
|
|
33
|
+
providers pueden agregarse desde los extras oficiales de Pydantic AI cuando un producto realmente
|
|
34
|
+
los necesite. Cortex no implementa adapters paralelos.
|
|
36
35
|
|
|
37
36
|
## Uso
|
|
38
37
|
|
|
@@ -113,6 +112,25 @@ agent = Agent(model)
|
|
|
113
112
|
|
|
114
113
|
El context manager de `Agent` administra el transporte del provider.
|
|
115
114
|
|
|
115
|
+
## Fallback del resultado de una tool
|
|
116
|
+
|
|
117
|
+
Pydantic AI reintenta cuando un modelo termina sin texto. Para tools cuyo resultado ya es una
|
|
118
|
+
respuesta completa, Cortex puede reutilizar el último resultado exitoso del mismo run:
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
from pydantic_ai import Agent
|
|
122
|
+
|
|
123
|
+
from cortex_agent_sdk.capabilities import last_tool_result_fallback
|
|
124
|
+
|
|
125
|
+
agent = Agent(
|
|
126
|
+
"openai-responses:gpt-5.6-luna",
|
|
127
|
+
capabilities=[last_tool_result_fallback({"confirmar_agenda"})],
|
|
128
|
+
)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
La aplicación conserva la decisión sobre las tools elegibles. La capacidad no usa resultados
|
|
132
|
+
fallidos, vacíos ni pertenecientes a otro run, y no reemplaza texto o nuevas llamadas del modelo.
|
|
133
|
+
|
|
116
134
|
## Migración desde el runtime anterior
|
|
117
135
|
|
|
118
136
|
| Antes | Ahora |
|
|
@@ -126,7 +144,7 @@ El context manager de `Agent` administra el transporte del provider.
|
|
|
126
144
|
| `AgentHooks` | `pydantic_ai.capabilities.Hooks` |
|
|
127
145
|
| `turn_finished` | `Hooks(after_run=...)` |
|
|
128
146
|
| `history_transform` | `Hooks(before_model_request=...)` |
|
|
129
|
-
| `fallback_answer` |
|
|
147
|
+
| `fallback_answer` | `last_tool_result_fallback(...)` opcional |
|
|
130
148
|
| `AgentOptions` | `UsageLimits`, settings del modelo y argumentos de `Agent` |
|
|
131
149
|
| `AgentResult.text` | `AgentRunResult.output` |
|
|
132
150
|
| `SessionStore.acquire` | `SessionStore.turn` + `Session.replace` |
|
|
@@ -141,6 +159,7 @@ Pydantic AI.
|
|
|
141
159
|
- `cortex_agent_sdk.sessions.SessionStore`
|
|
142
160
|
- `cortex_agent_sdk.sessions.MemorySessionStore`
|
|
143
161
|
- `cortex_agent_sdk.redis.RedisSessionStore`
|
|
162
|
+
- `cortex_agent_sdk.capabilities.last_tool_result_fallback`
|
|
144
163
|
- `cortex_agent_sdk.errores.AppError`
|
|
145
164
|
- `cortex_agent_sdk.errores.CodigoError`
|
|
146
165
|
- `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.0"
|
|
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>=2.27,<3",
|
|
20
|
+
"pydantic-ai-slim[google,openai]>=2.27,<3",
|
|
21
21
|
]
|
|
22
22
|
|
|
23
23
|
[project.urls]
|
|
@@ -25,20 +25,13 @@ 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
|
-
openai = [
|
|
29
|
-
"pydantic-ai-slim[openai]>=2.27,<3",
|
|
30
|
-
]
|
|
31
|
-
all = [
|
|
32
|
-
"pydantic-ai-slim[openai]>=2.27,<3",
|
|
33
|
-
"redis>=8.1.0",
|
|
34
|
-
]
|
|
28
|
+
openai = []
|
|
35
29
|
redis = [
|
|
36
30
|
"redis>=8.1.0",
|
|
37
31
|
]
|
|
38
32
|
|
|
39
33
|
[dependency-groups]
|
|
40
34
|
dev = [
|
|
41
|
-
"pydantic-ai-slim[openai]>=2.27,<3",
|
|
42
35
|
"pyright>=1.1.408",
|
|
43
36
|
"pytest>=9.0",
|
|
44
37
|
"pytest-asyncio>=1.3",
|
|
@@ -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
|