feat: generate improvement proposals

This commit is contained in:
robert
2026-07-18 13:50:46 -03:00
parent ef7bb53209
commit 5da42253fa
5 changed files with 31 additions and 10 deletions

View File

@@ -2,8 +2,8 @@
"schema_version": "2026-06-04", "schema_version": "2026-06-04",
"language": "python", "language": "python",
"name": "agent-reviewer", "name": "agent-reviewer",
"description": "Audit an A2A agent's source before deploy. Reads the target repo from Gitea, applies security / best-practice / grant-scope skill bundles, and returns a structured ReviewReport.", "description": "Pre-deploy audit of an A2A agent's source — security, scope, ergonomics.",
"version": "0.1.1", "version": "0.1.2",
"entrypoint": { "entrypoint": {
"module": "agent", "module": "agent",
"class_name": "AgentReviewer", "class_name": "AgentReviewer",
@@ -56,6 +56,9 @@
"type": "null" "type": "null"
} }
] ]
},
"mode": {
"type": "string"
} }
}, },
"required": [ "required": [
@@ -83,6 +86,7 @@
}, },
"runtime": { "runtime": {
"lifecycle": "ephemeral", "lifecycle": "ephemeral",
"availability": "on_demand",
"state": "none", "state": "none",
"sandbox": "microsandbox", "sandbox": "microsandbox",
"resources": { "resources": {
@@ -115,6 +119,7 @@
"memory": null, "memory": null,
"databases": [] "databases": []
}, },
"endpoints": [],
"apt_packages": [] "apt_packages": []
}, },
"template_lineage": null, "template_lineage": null,
@@ -151,7 +156,7 @@
"source": "python-a2a-pack", "source": "python-a2a-pack",
"project_manifest": { "project_manifest": {
"name": "agent-reviewer", "name": "agent-reviewer",
"version": "0.1.1", "version": "0.1.2",
"entrypoint": "agent:AgentReviewer" "entrypoint": "agent:AgentReviewer"
} }
} }

View File

@@ -7,7 +7,7 @@ returns a typed `ReviewReport`.
## Skill: `review` ## Skill: `review`
``` ```
review(agent_name: str, ref: str = "main", owner: str | None = None) -> ReviewReport review(agent_name: str, ref: str = "main", owner: str | None = None, mode: str = "audit") -> ReviewReport
``` ```
Workflow: Workflow:
@@ -19,6 +19,10 @@ Workflow:
(`a2a card`, `ruff`), produce findings. (`a2a card`, `ruff`), produce findings.
4. Release the Gitea token in `finally`. 4. Release the Gitea token in `finally`.
`mode="improvements"` keeps the same read-only checks and additionally asks
for at most three source-specific robustness, test, tool-usability, or
operator-ergonomics ideas. Agent Studio uses that mode for its daily review.
## Output ## Output
`ReviewReport`: `ReviewReport`:

View File

@@ -1,5 +1,5 @@
name: agent-reviewer name: agent-reviewer
version: 0.1.1 version: 0.1.2
entrypoint: agent:AgentReviewer entrypoint: agent:AgentReviewer
description: Pre-deploy audit of an A2A agent's source — security, scope, ergonomics. description: Pre-deploy audit of an A2A agent's source — security, scope, ergonomics.
expose: expose:

View File

@@ -8,8 +8,9 @@ from typing import Any
from pydantic import BaseModel from pydantic import BaseModel
import a2a_pack as a2a
from a2a_pack import ( from a2a_pack import (
A2AAgent, LLMProvisioning, NoAuth, Pricing, RunContext, skill, A2AAgent, LLMProvisioning, NoAuth, Pricing, RunContext,
) )
from agent_reviewer import ReviewerContext, build_reviewer_graph from agent_reviewer import ReviewerContext, build_reviewer_graph
@@ -30,7 +31,7 @@ class AgentReviewer(A2AAgent[ReviewerConfig, NoAuth]):
"repo from Gitea, applies security / best-practice / grant-scope " "repo from Gitea, applies security / best-practice / grant-scope "
"skill bundles, and returns a structured ReviewReport." "skill bundles, and returns a structured ReviewReport."
) )
version = "0.1.1" version = "0.1.2"
config_model = ReviewerConfig config_model = ReviewerConfig
auth_model = NoAuth auth_model = NoAuth
@@ -46,7 +47,7 @@ class AgentReviewer(A2AAgent[ReviewerConfig, NoAuth]):
), ),
) )
@skill( @a2a.tool(
description=( description=(
"Audit an agent's source. Pass the target ``agent_name`` " "Audit an agent's source. Pass the target ``agent_name`` "
"(kebab-case) and optional ``ref`` (defaults to ``main``). " "(kebab-case) and optional ``ref`` (defaults to ``main``). "
@@ -63,6 +64,7 @@ class AgentReviewer(A2AAgent[ReviewerConfig, NoAuth]):
agent_name: str, agent_name: str,
ref: str = "main", ref: str = "main",
owner: str | None = None, owner: str | None = None,
mode: str = "audit",
) -> dict[str, Any]: ) -> dict[str, Any]:
if not _is_valid_slug(agent_name): if not _is_valid_slug(agent_name):
return {"error": f"invalid agent_name {agent_name!r} — use kebab-case"} return {"error": f"invalid agent_name {agent_name!r} — use kebab-case"}
@@ -120,11 +122,21 @@ class AgentReviewer(A2AAgent[ReviewerConfig, NoAuth]):
completion_box=completion_box, completion_box=completion_box,
) )
improvement_brief = (
" This is a daily improvement-discovery review. In addition to real "
"defects, return at most three high-confidence, source-specific ideas "
"that improve robustness, test coverage, tool usability, or operator "
"ergonomics. Represent an idea as an info/ergonomics finding and put "
"the concrete implementation in suggestion. Do not invent work for a "
"clean agent."
if str(mode).strip().lower() == "improvements"
else ""
)
user_msg = ( user_msg = (
f"Review the agent at ``{gitea_owner}/{agent_name}`` ref ``{ref}``. " f"Review the agent at ``{gitea_owner}/{agent_name}`` ref ``{ref}``. "
"Read the source, consult the bundled skills, run the sandbox checks, " "Read the source, consult the bundled skills, run the sandbox checks, "
"then call ``submit_review_report`` exactly once with the structured " "then call ``submit_review_report`` exactly once with the structured "
"report." f"report.{improvement_brief}"
) )
async def _heartbeat() -> None: async def _heartbeat() -> None:

View File

@@ -21,7 +21,7 @@ from agent_reviewer.config import load_settings # noqa: E402
def test_class_metadata() -> None: def test_class_metadata() -> None:
assert AgentReviewer.name == "agent-reviewer" assert AgentReviewer.name == "agent-reviewer"
assert AgentReviewer.version == "0.1.1" assert AgentReviewer.version == "0.1.2"
assert AgentReviewer.wants_cp_jwt is True assert AgentReviewer.wants_cp_jwt is True
assert AgentReviewer.pricing.price_per_call_usd == 0.05 assert AgentReviewer.pricing.price_per_call_usd == 0.05
assert AgentReviewer.pricing.caller_pays_llm is True assert AgentReviewer.pricing.caller_pays_llm is True