llama-agents-agentcore 0.4.15__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.
- llama_agents_agentcore-0.4.15/PKG-INFO +21 -0
- llama_agents_agentcore-0.4.15/README.md +10 -0
- llama_agents_agentcore-0.4.15/pyproject.toml +31 -0
- llama_agents_agentcore-0.4.15/src/llama_agents/agentcore/__init__.py +0 -0
- llama_agents_agentcore-0.4.15/src/llama_agents/agentcore/entrypoint.py +134 -0
- llama_agents_agentcore-0.4.15/src/llama_agents/agentcore/export.py +12 -0
- llama_agents_agentcore-0.4.15/src/llama_agents/agentcore/main.py +19 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: llama-agents-agentcore
|
|
3
|
+
Version: 0.4.15
|
|
4
|
+
Summary: LlamaAgents x Bedrock AgentCore deployment utilities
|
|
5
|
+
Requires-Dist: bedrock-agentcore>=1.2.0
|
|
6
|
+
Requires-Dist: llama-deploy-core>=0.4.15,<0.5.0
|
|
7
|
+
Requires-Dist: llama-deploy-appserver>=0.4.15,<0.5.0
|
|
8
|
+
Requires-Dist: click>=8.3.1
|
|
9
|
+
Requires-Python: >=3.10, <4
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# LlamaAgents AgentCore
|
|
13
|
+
|
|
14
|
+
LlamaAgents x Bedrock AgentCore deployment utilities.
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
llamactl agentcore run # runs the server locally
|
|
20
|
+
llamactl agentcore export # exports code to a .agentcore/ directory
|
|
21
|
+
```
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["uv_build>=0.10.8,<0.11"]
|
|
3
|
+
build-backend = "uv_build"
|
|
4
|
+
|
|
5
|
+
[dependency-groups]
|
|
6
|
+
dev = [
|
|
7
|
+
"pytest>=8.4.2",
|
|
8
|
+
"pytest-asyncio>=0.25.3",
|
|
9
|
+
"ruff>=0.15.0",
|
|
10
|
+
"ty>=0.0.15"
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
[project]
|
|
14
|
+
name = "llama-agents-agentcore"
|
|
15
|
+
version = "0.4.15"
|
|
16
|
+
description = "LlamaAgents x Bedrock AgentCore deployment utilities"
|
|
17
|
+
readme = "README.md"
|
|
18
|
+
requires-python = ">=3.10,<4"
|
|
19
|
+
dependencies = [
|
|
20
|
+
"bedrock-agentcore>=1.2.0",
|
|
21
|
+
"llama-deploy-core>=0.4.15,<0.5.0",
|
|
22
|
+
"llama-deploy-appserver>=0.4.15,<0.5.0",
|
|
23
|
+
"click>=8.3.1"
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[tool.uv.build-backend]
|
|
27
|
+
module-name = "llama_agents.agentcore"
|
|
28
|
+
|
|
29
|
+
[tool.uv.sources]
|
|
30
|
+
llama-deploy-core = {workspace = true}
|
|
31
|
+
llama-deploy-appserver = {workspace = true}
|
|
File without changes
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
"""
|
|
3
|
+
AgentCore entrypoint for LlamaIndex Workflows.
|
|
4
|
+
Auto-generated by LlamaCloud — wraps workflows for AWS Bedrock AgentCore Runtime.
|
|
5
|
+
|
|
6
|
+
Uses BedrockAgentCoreApp with @app.entrypoint decorator for native AgentCore integration.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import functools
|
|
12
|
+
import logging
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Any, Literal, cast
|
|
15
|
+
|
|
16
|
+
from bedrock_agentcore import BedrockAgentCoreApp
|
|
17
|
+
from llama_deploy.appserver.workflow_loader import load_workflows
|
|
18
|
+
from llama_deploy.core.deployment_config import (
|
|
19
|
+
read_deployment_config_from_git_root_or_cwd,
|
|
20
|
+
)
|
|
21
|
+
from pydantic import BaseModel, ValidationError
|
|
22
|
+
from workflows import Workflow
|
|
23
|
+
from workflows.context.serializers import JsonSerializer
|
|
24
|
+
from workflows.events import StartEvent
|
|
25
|
+
|
|
26
|
+
logger = logging.getLogger(__name__)
|
|
27
|
+
app = BedrockAgentCoreApp()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class WorkflowResult(BaseModel):
|
|
31
|
+
workflow: str
|
|
32
|
+
status: Literal["completed", "failed"]
|
|
33
|
+
result: str | None = None
|
|
34
|
+
error: str | None = None
|
|
35
|
+
session_id: str | None = None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@functools.lru_cache(maxsize=1)
|
|
39
|
+
def _load_workflows() -> tuple[dict[str, Workflow], str, str | None]:
|
|
40
|
+
config_dir = Path.cwd()
|
|
41
|
+
if not (config_dir / "pyproject.toml").exists():
|
|
42
|
+
raise FileNotFoundError(
|
|
43
|
+
"No pyproject.toml found at "
|
|
44
|
+
f"{config_dir}.\n"
|
|
45
|
+
"Add a pyproject.toml to your project and re-run."
|
|
46
|
+
)
|
|
47
|
+
config = read_deployment_config_from_git_root_or_cwd(
|
|
48
|
+
Path.cwd(), config_dir
|
|
49
|
+
) # let errors bubble up if misconfigured
|
|
50
|
+
workflows = load_workflows(config)
|
|
51
|
+
has_default = any(key == "default" for key in list(workflows.keys()))
|
|
52
|
+
default_workflow = "default" if has_default else next(iter(workflows))
|
|
53
|
+
file_workflow = None
|
|
54
|
+
for name, wf in workflows.items():
|
|
55
|
+
if wf.start_event_class.__name__ == "FileEvent":
|
|
56
|
+
file_workflow = name
|
|
57
|
+
break
|
|
58
|
+
return workflows, default_workflow, file_workflow
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
async def _run_workflow(
|
|
62
|
+
workflow_name: str, wf: Workflow, start_event: StartEvent
|
|
63
|
+
) -> WorkflowResult:
|
|
64
|
+
"""Run a workflow by name with the given event data."""
|
|
65
|
+
try:
|
|
66
|
+
handler = wf.run(start_event=start_event)
|
|
67
|
+
result = await handler
|
|
68
|
+
except Exception as e:
|
|
69
|
+
logger.error("Workflow '%s' failed: %s", workflow_name, e, exc_info=True)
|
|
70
|
+
return WorkflowResult(
|
|
71
|
+
workflow=workflow_name, error=f"Workflow failed: {e}", status="failed"
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
return WorkflowResult(
|
|
75
|
+
workflow=workflow_name,
|
|
76
|
+
status="completed",
|
|
77
|
+
result=JsonSerializer().serialize(result),
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _parse_and_validate_payload(
|
|
82
|
+
workflows: dict[str, Any],
|
|
83
|
+
default_workflow: str,
|
|
84
|
+
file_workflow: str | None,
|
|
85
|
+
payload: dict,
|
|
86
|
+
) -> tuple[str, Workflow, StartEvent] | tuple[str, str]:
|
|
87
|
+
"""Parse incoming payload to determine workflow and event data.
|
|
88
|
+
|
|
89
|
+
Supports:
|
|
90
|
+
- Explicit: {"workflow": "process-file", "start_event": {"file_id": "123"}}
|
|
91
|
+
- Shorthand: {"file_id": "123"} -> routes to process-file workflow
|
|
92
|
+
- Default: {} -> routes to default workflow
|
|
93
|
+
"""
|
|
94
|
+
workflow_name = payload.get("workflow")
|
|
95
|
+
event_data = payload.get("start_event", {})
|
|
96
|
+
|
|
97
|
+
if not workflow_name:
|
|
98
|
+
if "file_id" in payload and file_workflow is not None:
|
|
99
|
+
workflow_name = file_workflow
|
|
100
|
+
event_data = {"file_id": payload["file_id"]}
|
|
101
|
+
else:
|
|
102
|
+
workflow_name = default_workflow
|
|
103
|
+
if workflow_name not in workflows:
|
|
104
|
+
return workflow_name, f"Workflow not found: {workflow_name}"
|
|
105
|
+
wf = workflows[workflow_name]
|
|
106
|
+
start_cls = wf.start_event_class
|
|
107
|
+
try:
|
|
108
|
+
data = start_cls.model_validate(event_data)
|
|
109
|
+
except ValidationError as e:
|
|
110
|
+
return workflow_name, f"Invalid input data: {e}"
|
|
111
|
+
return workflow_name, wf, data
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@app.entrypoint
|
|
115
|
+
async def invoke(payload: dict, context: Any) -> dict[str, Any]:
|
|
116
|
+
"""Main AgentCore entrypoint — routes to appropriate workflow."""
|
|
117
|
+
workflows, default_workflow, file_workflow = _load_workflows()
|
|
118
|
+
parsed = _parse_and_validate_payload(
|
|
119
|
+
workflows, default_workflow, file_workflow, payload
|
|
120
|
+
)
|
|
121
|
+
if len(parsed) == 2 and all(isinstance(p, str) for p in parsed):
|
|
122
|
+
workflow_name, error = cast(tuple[str, str], parsed)
|
|
123
|
+
return WorkflowResult(
|
|
124
|
+
workflow=workflow_name,
|
|
125
|
+
error=error,
|
|
126
|
+
status="failed",
|
|
127
|
+
session_id=getattr(
|
|
128
|
+
context, "session_id"
|
|
129
|
+
), # stay on the safe side with the session_id attribute on an unknown type
|
|
130
|
+
).model_dump()
|
|
131
|
+
workflow_name, wf, event = cast(tuple[str, Workflow, StartEvent], parsed)
|
|
132
|
+
result = await _run_workflow(workflow_name, wf, event)
|
|
133
|
+
result.session_id = getattr(context, "session_id")
|
|
134
|
+
return result.model_dump()
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
agentcore_dir = Path(".agentcore")
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def export_generated_entrypoint_code() -> None:
|
|
7
|
+
entrypoint = Path(__file__).parent / "entrypoint.py"
|
|
8
|
+
content = entrypoint.read_text()
|
|
9
|
+
agentcore_dir.mkdir(exist_ok=True)
|
|
10
|
+
with open(agentcore_dir / "entrypoint.py", "w") as f:
|
|
11
|
+
f.write(content)
|
|
12
|
+
return None
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from argparse import ArgumentParser
|
|
2
|
+
|
|
3
|
+
from .entrypoint import app
|
|
4
|
+
|
|
5
|
+
if __name__ == "__main__":
|
|
6
|
+
parser = ArgumentParser()
|
|
7
|
+
|
|
8
|
+
parser.add_argument(
|
|
9
|
+
"--run",
|
|
10
|
+
help="Run the application in the target environment",
|
|
11
|
+
action="store_true",
|
|
12
|
+
default=False,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
args = parser.parse_args()
|
|
16
|
+
|
|
17
|
+
if args.run:
|
|
18
|
+
print("Starting app on 0.0.0.0:8080") # noqa
|
|
19
|
+
app.run(port=8080, host="0.0.0.0")
|