Skip to content

Commit 99b560b

Browse files
Merge pull request #172 from valory-xyz/feat/agent_performance_endpoint
Agent performance endpoint
2 parents df4e440 + 4f365c1 commit 99b560b

File tree

5 files changed

+116
-5
lines changed

5 files changed

+116
-5
lines changed

docs/api.md

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,50 @@ Get service deployment information.
789789
}
790790
```
791791

792+
### `GET /api/v2/service/{service_config_id}/agent_performance`
793+
794+
Get agent performance information.
795+
796+
**Response (Success - 200):**
797+
798+
```json
799+
{
800+
"last_activity": {
801+
"title": "Last activity title",
802+
"description": "Last activity description",
803+
},
804+
"last_chat_message": "Agent last chat message",
805+
"metrics": [
806+
{
807+
"description": "Metric description",
808+
"is_primary": true,
809+
"name": "Metric name",
810+
"value": "Metric value"
811+
}
812+
],
813+
"timestamp": 1234567890
814+
}
815+
```
816+
817+
**Response (Success with empty agent performance - 200):**
818+
819+
```json
820+
{
821+
"last_activity": null,
822+
"last_chat_message": null,
823+
"metrics": [],
824+
"timestamp": null
825+
}
826+
```
827+
828+
**Response (Service not found - 404):**
829+
830+
```json
831+
{
832+
"error": "Service service_123 not found"
833+
}
834+
```
835+
792836
### `GET /api/v2/service/{service_config_id}/refill_requirements`
793837

794838
Get service refill requirements.
@@ -948,7 +992,7 @@ Create a new service.
948992
}
949993
```
950994

951-
### `PUT /api/v2/service/{service_config_id}` / `PATCH /api/v2/service/{service_config_id}`
995+
### `PUT /api/v2/service/{service_config_id}` <br /> `PATCH /api/v2/service/{service_config_id}`
952996

953997
Update a service configuration. Use `PUT` for full updates and `PATCH` for partial updates.
954998

operate/cli.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,21 @@ async def _get_service_deployment(request: Request) -> JSONResponse:
877877
deployment_json["healthcheck"] = service.get_latest_healthcheck()
878878
return JSONResponse(content=deployment_json)
879879

880+
@app.get("/api/v2/service/{service_config_id}/agent_performance")
881+
@with_retries
882+
async def _get_agent_performance(request: Request) -> JSONResponse:
883+
"""Get the service refill requirements."""
884+
service_config_id = request.path_params["service_config_id"]
885+
886+
if not operate.service_manager().exists(service_config_id=service_config_id):
887+
return service_not_found_error(service_config_id=service_config_id)
888+
889+
return JSONResponse(
890+
content=operate.service_manager()
891+
.load(service_config_id=service_config_id)
892+
.get_agent_performance()
893+
)
894+
880895
@app.get("/api/v2/service/{service_config_id}/refill_requirements")
881896
@with_retries
882897
async def _get_refill_requirements(request: Request) -> JSONResponse:

operate/constants.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@
2929
DEPLOYMENT_DIR = "deployment"
3030
DEPLOYMENT_JSON = "deployment.json"
3131
CONFIG_JSON = "config.json"
32+
33+
AGENT_PERSISTENT_STORAGE_DIR = "persistent_data"
34+
AGENT_PERSISTENT_STORAGE_ENV_VAR = "STORE_PATH"
35+
AGENT_LOG_DIR = "benchmarks"
36+
AGENT_LOG_ENV_VAR = "LOG_DIR"
37+
3238
ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"
3339

3440
ON_CHAIN_INTERACT_TIMEOUT = 120.0

operate/services/manage.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,14 @@
4040
from autonomy.chain.metadata import IPFS_URI_PREFIX
4141
from web3 import Web3
4242

43-
from operate.constants import IPFS_ADDRESS, ZERO_ADDRESS
43+
from operate.constants import (
44+
AGENT_LOG_DIR,
45+
AGENT_LOG_ENV_VAR,
46+
AGENT_PERSISTENT_STORAGE_DIR,
47+
AGENT_PERSISTENT_STORAGE_ENV_VAR,
48+
IPFS_ADDRESS,
49+
ZERO_ADDRESS,
50+
)
4451
from operate.data import DATA_DIR
4552
from operate.data.contracts.mech_activity.contract import MechActivityContract
4653
from operate.data.contracts.requester_activity_checker.contract import (
@@ -730,8 +737,8 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to
730737

731738
# Set environment variables for the service
732739
for dir_name, env_var_name in (
733-
("persistent_data", "STORE_PATH"),
734-
("benchmarks", "LOG_DIR"),
740+
(AGENT_PERSISTENT_STORAGE_DIR, AGENT_PERSISTENT_STORAGE_ENV_VAR),
741+
(AGENT_LOG_DIR, AGENT_LOG_ENV_VAR),
735742
):
736743
dir_path = service.path / dir_name
737744
dir_path.mkdir(parents=True, exist_ok=True)

operate/services/service.py

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,12 @@
6363
from autonomy.deploy.generators.kubernetes.base import KubernetesGenerator
6464
from docker import from_env
6565

66-
from operate.constants import CONFIG_JSON, DEPLOYMENT_DIR, DEPLOYMENT_JSON
66+
from operate.constants import (
67+
AGENT_PERSISTENT_STORAGE_ENV_VAR,
68+
CONFIG_JSON,
69+
DEPLOYMENT_DIR,
70+
DEPLOYMENT_JSON,
71+
)
6772
from operate.keys import KeysManager
6873
from operate.operate_http.exceptions import NotAllowed
6974
from operate.operate_types import (
@@ -927,6 +932,40 @@ def remove_latest_healthcheck(self) -> None:
927932
except Exception as e: # pylint: disable=broad-except
928933
print(f"Exception deleting {healthcheck_json_path}: {e}")
929934

935+
def get_agent_performance(self) -> t.Dict:
936+
"""Return the agent activity"""
937+
938+
# Default values
939+
agent_performance: t.Dict[str, t.Any] = {
940+
"timestamp": None,
941+
"metrics": [],
942+
"last_activity": None,
943+
"last_chat_message": None,
944+
}
945+
946+
agent_performance_json_path = (
947+
Path(
948+
self.env_variables.get(
949+
AGENT_PERSISTENT_STORAGE_ENV_VAR, {"value": "."}
950+
).get("value", ".")
951+
)
952+
/ "agent_performance.json"
953+
)
954+
955+
if agent_performance_json_path.exists():
956+
try:
957+
with open(agent_performance_json_path, "r", encoding="utf-8") as f:
958+
data = json.load(f)
959+
if isinstance(data, dict):
960+
agent_performance.update(data)
961+
except (json.JSONDecodeError, OSError) as e:
962+
# Keep default values if file is invalid
963+
print(
964+
f"Error reading file 'agent_performance.json': {e}"
965+
) # TODO Use logger
966+
967+
return dict(sorted(agent_performance.items()))
968+
930969
def update(
931970
self,
932971
service_template: ServiceTemplate,

0 commit comments

Comments
 (0)