feat: add world type system — programmatic & hosted modes#88
Merged
Jing-yilin merged 9 commits intomainfrom Mar 19, 2026
Merged
feat: add world type system — programmatic & hosted modes#88Jing-yilin merged 9 commits intomainfrom
Jing-yilin merged 9 commits intomainfrom
Conversation
Extend WorldManifest with: - type: 'programmatic' | 'hosted' - structured rules (WorldRule[]), actions (ActionSchema) - host info (HostInfo) for hosted worlds - lifecycle config (matchmaking, eviction, timeouts) Extend WorldConfig with worldType, hostAgentId, hostCardUrl, hostEndpoints. createWorldServer auto-injects host info into manifest on world.join when worldType is 'hosted'. All new fields are optional — fully backward compatible with existing worlds. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
## From autoresearch branch
Adds manifest normalization and documentation on top of the world types
feature.
### Changes
- **ActionSchema union type**: `StructuredActionSchema |
LegacyActionSchema` — preserves backward compat with old `{ params:
Record<string, string> }` format
- **buildManifest normalization**: `ensureRules()` auto-converts
`string[]` to `WorldRule[]`, `ensureActions()` upgrades legacy param
schemas
- **buildManifest defaults**: falls back to worldName/worldTheme from
config
- **docs/WORLD_MANIFEST.md**: comprehensive reference with programmatic
vs hosted comparison, manifest field docs, updated examples
- **world/server.mjs template**: updated to use structured
rules/actions/lifecycle
### Removed
- autoresearch scaffolding (autoresearch.sh, .md, .jsonl)
---------
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Remove LegacyActionSchema, string[] rules support, and all normalization helpers (ensureRules, ensureActions, normalizeActionParams). Project is still in development with no external users. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Bootstrap node now stores and forwards capabilities field.
DAP plugin peer-discovery now passes capabilities through all
upsert calls. This fixes list_worlds/join_world which depend on
findPeersByCapability('world:') to discover world agents.
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Allows agents to specify custom event types (e.g. world.join) when sending direct messages. Default port now uses configured peerPort instead of hardcoded 8099.
## Summary
Aligns the DAP plugin's request signing with the AgentWire v0.2 spec.
Previously, requests used body-only signatures (v0.1 style). Now
outbound HTTP requests include `X-AgentWorld-*` headers with
method/path/authority/Content-Digest binding for cross-endpoint replay
resistance.
## Changes
### Client-side (outbound)
- `peer-client.ts`: `sendViaHttp` now produces all 6 `X-AgentWorld-*`
signing headers
- `peer-discovery.ts`: `announceToNode` sends v0.2 header-signed
announces
- Body still carries legacy `signature` field for backward compat with
un-upgraded receivers
### Server-side (inbound)
- `peer-server.ts`: Dual-mode verification — checks
`X-AgentWorld-Signature` header first, falls back to body `signature` if
absent
- Added `rawBody` content parser to preserve original body for
Content-Digest verification
- Refactored response signing to use shared `signHttpResponse` from
identity module
### Shared utilities
- `identity.ts`: Added `signHttpRequest`, `verifyHttpRequestHeaders`,
`signHttpResponse`, `verifyHttpResponseHeaders`, `computeContentDigest`
- `types.ts`: Added `AwRequestHeaders` / `AwResponseHeaders` interfaces
### v0.2 signing input (per spec §6.6)
```json
{"v":"0.2","from":"aw:sha256:...","kid":"#identity","ts":"ISO8601","method":"POST","authority":"host:port","path":"/peer/message","contentDigest":"sha-256=:...:" }
```
### Tests
- 12 new tests in `test/request-signing.test.mjs` covering:
- Header production (all 6 required headers)
- Round-trip sign + verify
- Tampered body rejection (Content-Digest mismatch)
- Wrong public key rejection
- Path replay rejection (cross-endpoint)
- Expired timestamp rejection
- `sendP2PMessage` end-to-end delivery with v0.2 headers
- Legacy body-only signature backward compat
- Server-side dual-mode acceptance
- All 109 tests pass (97 existing + 12 new)
## What this does NOT change
- Body format (`P2PMessage`) unchanged — backward compat preserved
- UDP/QUIC path unchanged (no HTTP headers for UDP)
- No Agent Card requirement added
- No A2A JSON-RPC migration
- Domain-separated signatures across SDK and DAP plugin (HTTP_REQUEST, HTTP_RESPONSE, MESSAGE, KEY_ROTATION) - Header signatures (X-AgentWorld-*) required — no legacy body-only fallback - QUIC/UDP transport aligned with DOMAIN_SEPARATORS.MESSAGE - Blockchain-inspired World Ledger: SHA-256 hash chain, Ed25519-signed entries, JSON Lines persistence - Collision-resistant ledger filenames via SHA-256(worldId) - /world/ledger + /world/agents HTTP endpoints - Agent Card profiles: core (removed v0.2 spec version references)
…ation to minor Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
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
Adds a world type system to the Agent World SDK, supporting two modes:
Programmatic — World logic driven by fixed program (e.g. Pokemon Arena, Chess). No host agent needed.
Hosted — World created by a host agent (e.g. Coffee Chat Cafe). Visitors get host's contact info for direct P2P communication.
SDK Changes
New types (
types.ts)WorldRule— structured rules withenforcedflagActionSchema/ActionParamSchema— action declarations with typed paramsHostInfo— host agent identity + endpoints for hosted worldsWorldLifecycle— matchmaking, eviction, timeout configurationWorldManifest extensions (all optional, backward compatible)
type:"programmatic" | "hosted"rules:WorldRule[](also accepts legacystring[])actions:Record<string, ActionSchema>host:HostInfolifecycle:WorldLifecycleWorldConfig extensions
worldType,hostAgentId,hostCardUrl,hostEndpointscreateWorldServer behavior
world.joinviaenrichManifest()Tests