Skip to content

feat: add world type system — programmatic & hosted modes#88

Merged
Jing-yilin merged 9 commits intomainfrom
feat/world-types
Mar 19, 2026
Merged

feat: add world type system — programmatic & hosted modes#88
Jing-yilin merged 9 commits intomainfrom
feat/world-types

Conversation

@Jing-yilin
Copy link
Contributor

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 with enforced flag
  • ActionSchema / ActionParamSchema — action declarations with typed params
  • HostInfo — host agent identity + endpoints for hosted worlds
  • WorldLifecycle — matchmaking, eviction, timeout configuration

WorldManifest extensions (all optional, backward compatible)

  • type: "programmatic" | "hosted"
  • rules: WorldRule[] (also accepts legacy string[])
  • actions: Record<string, ActionSchema>
  • host: HostInfo
  • lifecycle: WorldLifecycle

WorldConfig extensions

  • worldType, hostAgentId, hostCardUrl, hostEndpoints

createWorldServer behavior

  • Programmatic: unchanged
  • Hosted: auto-injects host info into manifest on world.join via enrichManifest()

Tests

  • 97/97 existing tests pass
  • All new fields are optional — fully backward compatible

Jing-yilin and others added 9 commits March 18, 2026 15:12
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>
@Jing-yilin Jing-yilin merged commit eb4863f into main Mar 19, 2026
3 checks passed
@Jing-yilin Jing-yilin deleted the feat/world-types branch March 19, 2026 09:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant