You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: WebModelContext/explainer.md
+73-64Lines changed: 73 additions & 64 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -84,15 +84,9 @@ Handling tool cools in the main thread with the option of workers serves a few p
84
84
-**Complexity overhead**: In cases where the site UI is very complex, developers will likely need to do some refactoring or add JavaScript that handles app and UI state with appropriate outputs.
85
85
-**Tool discoverability**: There is no built-in mechanism for client applications to discover which sites provide callable tools without visiting or querying them directly. Search engines, or directories of some kind may play a role in helping client applications determine whether a site has relevant tools for the task it is trying to perform.
86
86
87
-
### API Options
87
+
### API
88
88
89
-
The `window.agent` interface is introduced to represent an abstract AI agent that is connected to the page and uses the page's context. Below are the options being considered for the exact interface:
90
-
91
-
#### Option 1: Combined tool definition and implementation
92
-
93
-
The simplest approach, and one that aligns closely with libraries like the MCP SDK is to have a single API that lets the web developer declare tools and provide their implementations in a single call:
94
-
95
-
**Example:**
89
+
The `window.agent` interface is introduced to represent an abstract AI agent that is connected to the page and uses the page's context. The `agent` object has a single method `provideContext` that's used to update the context (currently just tools) available to the agent. The method takes an object with a `tools` property which is a list of tool descriptors. The tool descriptors look as shown in this example below, which aligns with the Prompt API's [tool use](https://github.com/webmachinelearning/prompt-api#tool-use) specification, and other libraries like the MCP SDK:
96
90
97
91
```js
98
92
// Declare tool schema and implementation functions.
text: { type:"string", description:"The text of the todo item" }
108
102
},
109
103
required: ["text"]
110
104
},
111
-
asyncrun(params) => {
105
+
asyncexecute({ text }) => {
112
106
// Add todo item and update UI.
113
107
return/* structured content response */
114
108
}
115
109
}
116
110
]
117
111
});
118
112
```
113
+
114
+
The `provideContext` method can be called multiple times. Subsequent calls clear any pre-existing tools and other context before registering the new ones. This is useful for single-page web apps that frequently change UI state and could benefit from presenting different tools depending on which state the UI is currently in.
115
+
119
116
**Advantages:**
120
117
118
+
- Aligns with existing APIs.
121
119
- Simple for web developers to use.
122
120
- Enforces a single function per tool.
123
121
124
122
**Disadvantages:**
125
123
126
-
- Must navigate to the page and run JavaScript for tools to be defined.
124
+
- Must navigate to the page and run JavaScript for agent to discover tools.
127
125
128
-
#### Option 2: Separate tool definition and implementation (**Recommended**)
126
+
If Web Model Context gains traction in the web developer community, it will become important for agents to have a way to discover which sites have tools that are relevant to a user's request. Discovery is a topic that may warrant its own explainer, but suffice to say, it may be beneficial for agents to have a way to know what capabilities a page offers without having to navigate to the web site first. As an example, a future iteration of this feature could introduce declarative tools definitions that are placed in an app manifest so that agents would only need to fetch the manifest with a simple HTTP GET request. Agents will of course still need to navigate to the site to actually use its tools, but a manifest makes it far less costly to discover these tools and reason about their relevance to the user's task.
129
127
130
-
Defining and implementing the tools separately opens the possibility of declaring tools outside of JavaScript. A future iteration of this feature could for example introduce tools that are defined declaratively in an app manifest so that agents can discover these without needing to visit the web site first. Agents will of course still need to navigate to the site to actually use its tools, but a manifest makes it far less costly to discover these tools and reason about their relevance to the user's task.
128
+
To make such a scenario easier, it would be beneficial to support an alternate means of tool call execution; one that separates the tool defintion and schema (which may exist in an external manifest file) from the implementation function.
131
129
132
-
**Example:**
130
+
One way to do this is to handle tool calls as events, as shown below:
@@ -158,17 +161,21 @@ window.agent.addEventListener('toolcall', async e => {
158
161
} // etc...
159
162
});
160
163
```
164
+
161
165
Tool calls are handled as events. Since event handler functions can't respond to the agent by returning a value directly, the `'toolcall'` event object has a `respondWith()` method that needs to be called to signal completion and respond to the agent. This is based on the existing service worker `'fetch'` event.
162
166
163
167
**Advantages:**
164
168
165
-
- Allows multiple different discovery mechanisms.
169
+
- Allows additional context different discovery mechanisms without rendering a page.
166
170
167
171
**Disadvantages:**
168
172
169
173
- Slightly harder to keep definition and implementation in sync.
174
+
- Potentially large switch-case in event handler.
175
+
176
+
#### Recommendation
170
177
171
-
Although this API is slightly more complex than the former, support for declaring tools outside of JavaScript will likely be important to support agents' ability to discover tools without needing to navigate to a page. It is also simple to write a wrapper around the Option 2 API that makes it look like Option 1, which could be useful for sites that don't want to take advantage of the declarative approach.
178
+
A **hybrid** approach of both of the examples above is recommended as this would make it easy for web developers to get started adding tools to their page, while leaving open the possibility of manifest-based approaches in the future. To implement this hybrid approach, a `"toolcall"` event is dispatched on every incoming tool call _before_ executing the tool's `execute` function. The event handler can handle the tool call by calling the event's `preventDefault()` method, and then responding to the agent with `respondWith()` as shown above. If the event handle does not call `preventDefault()` then the browser's default behavior for tool calls will occur. The `execute` function for the requested tool is called. If a tool with the requested name does not exist, then the browser responds to the agent with an error.
172
179
173
180
#### Other API alternatives considered
174
181
@@ -201,7 +208,7 @@ The page shows the stamps currently in the database and has a form to add a new
201
208
202
209
sing the Web Model Context API, the author can add just a few simple tools to the page for adding, updating, and retrieving stamps. With these relatively simple tools, an AI agent would have the ability to perform complex tasks like the ones illustrated above on behalf of the user.
203
210
204
-
The example below walks through adding one such tool, the "add-stamp" tool, using Option #2 of the Web Model Context API, so that AI agents can update the stamp collection.
211
+
The example below walks through adding one such tool, the "add-stamp" tool, using the Web Model Context API, so that AI agents can update the stamp collection.
205
212
206
213
The webpage today is designed with a visual UX in mind. It uses simple JavaScript with a `'submit'` event handler that reads the form fields, adds the new record, and refreshes the UI:
207
214
@@ -236,47 +243,49 @@ function addStamp(stampName, stampDescription, stampYear, stampImageUrl) {
236
243
}
237
244
```
238
245
239
-
To let AI agents use this functionality, the author first defines the available tools. The `agent` property on the `Window` is checked to ensure the browser supports Web Model Context. If supported, the `provideContext()` method is called, passing in an array of tools with a single item, a definition for the new "Add Stamp" tool. The tool accepts as parameters the same set of fields that are present in the HTML form, since this tool and the form should be functionally equivalent.
246
+
To let AI agents use this functionality, the author defines the available tools. The `agent` property on the `Window` is checked to ensure the browser supports Web Model Context. If supported, the `provideContext()` method is called, passing in an array of tools with a single item, a definition for the new "Add Stamp" tool. The tool accepts as parameters the same set of fields that are present in the HTML form, since this tool and the form should be functionally equivalent.
240
247
241
248
```js
242
-
window.agent.provideContext({
243
-
tools: [
244
-
{
245
-
name:"add-stamp",
246
-
description:"Add a new stamp to the collection",
247
-
params: {
248
-
type:"object",
249
-
properties: {
250
-
name: { type:"string", description:"The name of the stamp" },
251
-
description: { type:"string", description:"A brief description of the stamp" },
252
-
year: { type:"number", description:"The year the stamp was issued" },
253
-
imageUrl: { type:"string", description:"An optional image URL for the stamp" }
249
+
if ("agent"inwindow) {
250
+
window.agent.provideContext({
251
+
tools: [
252
+
{
253
+
name:"add-stamp",
254
+
description:"Add a new stamp to the collection",
255
+
inputSchema: {
256
+
type:"object",
257
+
properties: {
258
+
name: { type:"string", description:"The name of the stamp" },
259
+
description: { type:"string", description:"A brief description of the stamp" },
260
+
year: { type:"number", description:"The year the stamp was issued" },
261
+
imageUrl: { type:"string", description:"An optional image URL for the stamp" }
Now the author needs to handle tool calls coming from connected agents. After defining the "Add Stamp" tool above, the author handles the `'toolcall'` event and implements the tools operations. The tool needs to update the stamp database, and refresh the UI to reflect the change to the database. Since the code to do this is already available in the `addStamp()` function written earlier, the event handler is very simple and just needs to call this helper when an "add-stamp" tool call is received. After calling the helper, the event handler needs to signal completion and should also provide some sort of feedback to the client application that requested the tool call. It calls `e.respondWith()` with a text message indicating the stamp was added:
274
+
Now the author needs to implement the tool. The tool needs to update the stamp database, and refresh the UI to reflect the change to the database. Since the code to do this is already available in the `addStamp()` function written earlier, the tool implementation is very simple and just needs to call this helper when an "add-stamp" tool call is received. After calling the helper, the tool needs to signal completion and should also provide some sort of feedback to the client application that requested the tool call. It returns a text message indicating the stamp was added:
0 commit comments