feat: complete public EW tool catalog (_jw) - #1
Open
CharmingKillr wants to merge 3 commits into
Open
Conversation
zhangjun221
previously approved these changes
Jul 15, 2026
There was a problem hiding this comment.
Pull request overview
This PR completes B1 by adding a clean-room implementation of Emergence World’s currently public tool catalog, wiring it into the full scenario configuration, and adding tests/docs to lock in 113/113 catalog coverage and router discoverability.
Changes:
- Add
EWToolSpaceto implement/register the non-specialized portion of the public EW tool catalog with bounded state/query behavior, idempotency, persistence, and category gating. - Add
EconomySpaceto implement the EW ComputeCredits economy tools as a custom AgentSociety environment. - Add coverage/scale tests plus scenario/docs updates to reflect the public 113-tool boundary and ensure tooling is mounted and counted correctly.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
tests/test_ew_tool_catalog.py |
Adds catalog coverage, router registration, bounds/idempotency, and resume tests for EWToolSpace + union coverage checks. |
tests/test_ew_economy_space.py |
Adds functional and discoverability tests for the ComputeCredits economy tool batch and M4 counting. |
scenarios/ew-economic-smoke.yaml |
Adds a deterministic smoke scenario for EconomySpace tool calls. |
scenarios/ew_full.yaml |
Mounts EWToolSpace into the full scenario env list. |
README.md |
Updates top-level README to document the B1 113/113 public tool coverage boundary. |
docs/technical-architecture.md |
Updates architecture narrative/tables to reflect B1 completion and remaining boundaries. |
docs/progress-summary.md |
Updates progress summary to reflect B1 completion and revised remaining gaps. |
custom/envs/ew_tool_space.py |
Implements scalable EWToolSpace with generated tool methods, bounded state, persistence, and category gating. |
custom/envs/ew_tool_space_agent_skills/ew-world-tools/SKILL.md |
Adds agent-facing guidance for using EWToolSpace tools via ask_environment. |
custom/envs/economy_space.py |
Implements EconomySpace (wallet/bank/pitch cycles) and exposes tool methods for router discovery. |
CONTRIBUTING.md |
Marks B1 complete and documents scope/boundaries and acceptance criteria updates. |
afi/world/scenario.py |
Adds EWToolSpace builder wiring (names/homes/landmarks/constitution/bounds/category gating). |
afi/world/ew_tools.py |
Adds authoritative public EW catalog (113 unique names) for coverage checks. |
.agentsociety/env_modules/ewtoolspace.json |
Adds AgentSociety env module metadata for EWToolSpace (currently includes local absolute paths). |
.agentsociety/custom_env_skill/runs/b1-ew-complete/validation_summary.md |
Adds validation summary artifact for EWToolSpace registration/scan/test. |
.agentsociety/custom_env_skill/runs/b1-ew-complete/validation_report.json |
Adds validation report artifact (currently includes local absolute paths). |
.agentsociety/custom_env_skill/runs/b1-ew-complete/run_state.json |
Adds validation run state artifact (currently includes local absolute paths). |
.agentsociety/custom_env_skill/runs/b1-ew-complete/request.json |
Adds validation request artifact for the recorded run. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+1
to
+9
| { | ||
| "type": "EWToolSpace", | ||
| "class_name": "EWToolSpace", | ||
| "description": "EW public tool catalog: navigation, memory, content, community, identity, events, and utilities.", | ||
| "init_description": "EWToolSpace supplies the public Emergence World tools not owned by specialized modules.\n\n It is sized for 10 agents and 360 steps by default, with indexed per-agent\n state, bounded query responses, capped event history, replay snapshots,\n resume support, same-step idempotency, and optional category gating to keep\n the active LLM tool surface small. Each operation is exposed under\n its exact EW tool name and accepts **agent_id** plus an extensible **request**\n dictionary. Common request keys are target_id, content, query, item_id,\n limit, place, x, z, date, title, and metadata.\n ", | ||
| "is_custom": true, | ||
| "module_path": "custom/envs/ew_tool_space.py", | ||
| "file_path": "/Users/wei/Desktop/Tele工作相关/自由岛/afi-platform/custom/envs/ew_tool_space.py" | ||
| } No newline at end of file |
| @@ -0,0 +1,22 @@ | |||
| { | |||
| "run_id": "b1-ew-complete", | |||
| "workspace_path": "/Users/wei/Desktop/Tele工作相关/自由岛/afi-platform", | |||
Comment on lines
+2
to
+4
| "success": true, | ||
| "workspace_path": "/Users/wei/Desktop/Tele工作相关/自由岛/afi-platform", | ||
| "module_path": "custom/envs/ew_tool_space.py", |
Comment on lines
+8
to
+11
| "module_kind": "env_module", | ||
| "module_path": "custom/envs/ew_tool_space.py", | ||
| "file_path": "/Users/wei/Desktop/Tele工作相关/自由岛/afi-platform/custom/envs/ew_tool_space.py", | ||
| "class_name": "EWToolSpace", |
Comment on lines
+307
to
+309
| if name == "assign_relationship": | ||
| target = int(req.get("target_id", 0)); key = f"{aid}:{target}" | ||
| return self._write_once(name, aid, req, lambda: self._set_map(self._relationships, key, {"agent_id": aid, "target_id": target, "type": req.get("type", "acquaintance")}, "target_id")) |
Comment on lines
+310
to
+313
| if name == "rate_agent_trust": | ||
| target = int(req.get("target_id", 0)); key = f"{aid}:{target}" | ||
| rating = min(5, max(1, int(req.get("rating", 3)))) | ||
| return self._write_once(name, aid, req, lambda: self._set_map(self._trust, key, {"rater": aid, "target": target, "rating": rating, "reason": req.get("reason", "")}, "target_id")) |
Comment on lines
+419
to
+428
| def _execute_expression(self, req: dict) -> dict: | ||
| code = str(req.get("code", "")) | ||
| try: | ||
| tree = ast.parse(code, mode="eval") | ||
| allowed = (ast.Expression, ast.Constant, ast.List, ast.Tuple, ast.Dict, ast.Set, ast.BinOp, ast.UnaryOp, ast.BoolOp, ast.Compare, ast.operator, ast.unaryop, ast.boolop, ast.cmpop) | ||
| if any(not isinstance(node, allowed) for node in ast.walk(tree)): raise ValueError("only literal arithmetic expressions are allowed") | ||
| result = eval(compile(tree, "<ew-tool>", "eval"), {"__builtins__": {}}, {}) | ||
| return {"status": "success", "result": repr(result)[:4000]} | ||
| except Exception as exc: | ||
| return {"status": "fail", "reason": str(exc)} |
Comment on lines
+209
to
+213
| @tool(readonly=True, kind="observe") | ||
| async def get_person(self, id: int) -> dict: | ||
| """:param id: Agent ID.""" | ||
| async with self._lock: | ||
| return dict(self._persons[id]) |
Comment on lines
+247
to
+256
| @tool(readonly=False) | ||
| async def set_person_consumption(self, id: int, consumption: float) -> dict: | ||
| """:param id: Agent ID. :param consumption: New per-day consumption.""" | ||
| async with self._lock: | ||
| person = self._person(id) | ||
| if not person: | ||
| return {"old_consumption": 0.0, "new_consumption": float(consumption)} | ||
| old = person["consumption"] | ||
| person["consumption"] = float(consumption) | ||
| return {"old_consumption": old, "new_consumption": person["consumption"]} |
Comment on lines
+265
to
+274
| @tool(readonly=False) | ||
| async def set_person_income(self, id: int, income: float) -> dict: | ||
| """:param id: Agent ID. :param income: New per-day income.""" | ||
| async with self._lock: | ||
| person = self._person(id) | ||
| if not person: | ||
| return {"old_income": 0.0, "new_income": float(income)} | ||
| old = person["income"] | ||
| person["income"] = float(income) | ||
| return {"old_income": old, "new_income": person["income"]} |
zhangjun221
approved these changes
Jul 16, 2026
zhangjun221
left a comment
Owner
There was a problem hiding this comment.
Removed local .agentsociety validation artifacts and machine-specific paths from the PR branch; functional scope unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Completes CONTRIBUTING B1 for the currently public Emergence World catalog. The
_jwsuffix identifies the contributor.tools/README.mdEWToolSpacefor the 101 names not owned by specialized afi environmentsew_full.yamland adds machine-verifiable catalog coverageValidation
pytest -q: 11 passedreact.actionnames are counted as distinct toolsHonest boundary
Live news, web, papers, weather, and image generation use an
in_progressprovider request contract and do not fabricate results when no provider is configured. A live-model smoke attempt timed out at the external model response stage, so it is not claimed as passing; deterministic router, registry, handler, persistence, and M4 checks are included instead.Attribution
Tool names and semantics were clean-room adapted from EmergenceAI/Emergence-World under its research license; upstream code was not copied.