Agotalk Page Agent API (v1)
This is the runtime contract for a self-contained local static_browser page that exposes structured reads and actions to its Agotalk role agent.
Producer: the Agotalk App injects window.agotalk.expose(...) into a local browser page.
Consumer: a role documents the methods its page exposes, then invokes them through invoke_page_method.
Owner: the page owns its domain state and rules. Agotalk transports a pure-JSON call and result; it does not interpret the domain.
Register one function table
Register exactly once for each loaded document:
window.agotalk.expose({
read_current: () => pageState.read(),
apply_change: async (args) => pageState.apply(args)
});
expose(...) accepts one non-empty, flat object whose values are functions. Each function may be synchronous or asynchronous. Its result must be pure JSON.
read_current and apply_change are examples only. Method names, arguments, results, and domain rules belong entirely to the role-page contract: a design tool, tutor, game, or simulator may each expose different methods. The runtime does not accept API metadata such as version, methods, description, effect, or inputSchema; document those semantics in the role package instead.
Reloading or navigating replaces the document and clears its registration. A document cannot merge or replace a registration after it succeeds.
Agent tool
The role invokes a method it has documented for the current local page:
invoke_page_method({ tabId, method, args? })
tabId and method are required. args is an optional JSON object and defaults to {}. There is no general JavaScript evaluation surface and no runtime method-discovery tool. A role must document its own method table.
For example, a role that documents read_current and apply_change can call:
invoke_page_method({ tabId, method: "read_current", args: {} })
invoke_page_method({ tabId, method: "apply_change", args: { change: { kind: "move", target: "header" }, expectedRevision: 7 } })
The result is the registered function's JSON value.
State and writes
The page remains the only owner of state. Human UI actions and page methods must call the same domain commit path.
For state that both a human and an agent can change, expose a monotonic revision from the read method. Every write accepts expectedRevision and rejects stale input without changing state:
{
"ok": false,
"error": { "code": "STALE_STATE" },
"state": { "revision": 8 }
}
A successful write should return the new state in the same result. This gives the agent an authoritative receipt without another read call.
Large history or audit data should use a separate read method with an offset. Keep the ordinary observation bounded.
Page-initiated thread notification
In Agotalk App builds that support thread_notify, a local file page opened in a thread-owned tab can ask that same thread to take another turn:
async function notifyReview() {
if (typeof window.agotalk?.post !== "function") return false;
try {
const result = await window.agotalk.post("thread_notify", {
message: "请点评作文"
});
return result.ok === true && result.data?.disposition === "queued";
} catch {
return false;
}
}
The message must be non-empty and at most 8192 UTF-8 bytes. The page supplies only message; Agotalk identifies the owning thread and tab from the sending page. Standalone tabs and external URLs cannot use this topic. A successful response is { ok: true, data: { disposition: "queued", deliveryId } }: queued means the thread input was accepted, not that the agent has finished the requested work. Unsupported App builds and failed deliveries return { ok: false, error }. If notifyReview() returns false, keep the request visible and tell the child to ask for a review in the conversation.
The notification carries the tab ID to the agent. Document in the role's instructions which exposed read method the agent should call after waking, then which write method completes the action. For example, a writing page can save a review request locally, notify its thread, and let the role call observe followed by submit_review. Human actions and agent writes still use the same page-owned commit path and revision checks.
This is a one-way wakeup, not an event subscription or a completion callback. Keep the page usable when the notification cannot be sent.
Failure semantics
Agotalk reports transport or runtime failures with stable PAGE_API_* codes, including:
PAGE_API_NOT_EXPOSED
PAGE_API_ALREADY_EXPOSED
PAGE_API_CONTRACT_INVALID
PAGE_API_METHOD_NOT_FOUND
PAGE_API_ARGS_INVALID
PAGE_API_METHOD_FAILED
PAGE_API_RESULT_NOT_JSON
PAGE_API_TIMEOUT
PAGE_API_PAGE_CHANGED
PAGE_API_TAB_NOT_FOUND
PAGE_API_CALL_FAILED
Domain refusals belong to the page and should be returned, rather than thrown, as JSON values with their own stable codes. A failed write must not change domain state.
Non-goals
Page Agent API does not provide Node.js, general Electron APIs, shell access, MCP, event subscriptions, method discovery, or domain intelligence. Its structured calls transport only the domain contract that the page explicitly declares; thread_notify is the narrow page-to-thread notification above.