Agent Keys
Agent keys authenticate MCP, the REST API, and the cowl CLI. A key belongs to one organization and can be bound to one workspace. The same key and permissions work on all three surfaces. See the REST API reference and /api/v1/openapi.json.
Create a key
Go to Admin > Settings > API.
- Enter a key name that explains the automation, for example docs-agent or openapi-sync.
- Choose a workspace. Pick one workspace for least privilege, or Whole organization when the agent must operate across workspaces.
- Choose permissions. Use All permissions for a fully trusted automation, a group checkbox for one workflow area, or individual checkboxes for exact access.
- Choose an expiry. When your organization limits the key lifetime, the form offers only the expiries within the limit.
- Create the key and copy the token immediately.
The plaintext token starts with cowl_pat_ and is shown once. After that, ContextOwl stores only the hash and display prefix.
Scope model
- Organization: every request is tenant-scoped by the key owner.
- Workspace: a bound key can only read or write that workspace.
- Permissions: explicit capabilities such as article.read or workspace.create.
- Role ceiling: the owner's org role must also allow the action.
- Member scope: if the owner is restricted to assigned workspaces, the key inherits that restriction.
- Drafts: when Published pages only is on, a key reads DRAFT and IN REVIEW articles only with article.create, article.update, article.propose, article.publish, or article.place. Other keys read published articles only.
Workspace-bound keys may omit the workspace argument in MCP tools. Organization-wide keys must pass a workspace argument for workspace-scoped tools.
Published pages only
Published pages only in Admin > Settings > API keeps unfinished pages away from agents that can't write articles. New organizations have it on. Organizations created before the setting have it off until an admin turns it on.
When the setting is on, a key without article.create, article.update, article.propose, article.publish, or article.place reads BETA, STABLE, and DEPRECATED articles only:
- Search, suggestions, list_articles, and the sidebar resource leave out DRAFT and IN REVIEW articles, also with published_only set to false.
- get_article, the article resource, and the REST getArticle answer not_found for such an article and for a slug that redirects to one.
- listSections counts only the articles that the key can read.
An agent that a reader connects through the signed-in MCP endpoint holds no article write permission. With the setting on, it reads published pages only, whatever the role of the reader.
To let an agent read drafts, create a replacement key that also holds article.propose, and then revoke the old key. article.propose is a read-tier permission, so a viewer can hold it, and the agent can only suggest changes for review. You can also turn the setting off.
The analytics tools don't follow the setting. agent_insights, get_analytics_report, and get_content_insights can name draft pages to a key with analytics.read. list_openapi_pages names generated API pages of every status to a key with openapi.read.
Check a key
To see what a key can do, call whoami over MCP, call GET /api/v1/me over REST, or run cowl whoami. The result names the key, its prefix, and its expiry. It also gives the organization and its plan, the role of the owner, the workspaces that the key reaches, and the permissions that the key can use.
blocked lists the permissions that the key holds but can't use, each with a reason:
- role: the role of the owner doesn't allow the permission.
- two_factor: the organization requires admins to turn on two-factor auth, and the owner hasn't turned it on.
- plan: the plan of the organization doesn't include the permission.
readsDrafts is true when the key reads DRAFT and IN REVIEW articles, and false when it reads published articles only.
writes says how the changes of the key to live content apply: none when the key can't change content that readers see, review when the changes wait for an editor, and direct when they go live at once. publishingKey is true for a publishing key.
The result never holds an email address or a user id.
Permission picker
The permission picker is grouped by workflow:
| Group | What it controls |
|---|---|
| Content | Search, read, create, update, publish, and propose articles |
| Landing | Read, propose, and directly update the workspace landing page |
| Navigation | Create sections and place articles in the sidebar |
| Changelog | Read, create, update, publish, and delete changelog entries |
| Workspaces | Create, update, and delete workspaces |
| OpenAPI | Attach, sync, detach, and arrange generated API reference docs |
| Analytics | Read the analytics report, what agents ask, and the next steps for your docs |
| Other | Upload images for Markdown and landing pages |
Every key can list the workspaces that it reaches. That needs no permission.
Select All permissions only for trusted automations. For most agents, select one group and remove any permissions the agent does not need.
Revoke access
Delete the key from Admin > Settings > API. Future requests using that token return 401. An admin can also revoke the key of any member in Member keys.
Member keys
Admins see the live agent keys of the other members in Admin > Settings > API > Member keys. Each row names the owner, the role, the workspace, the expiry, and the last use.
- Select Activity to open the audit log with the changes of that key.
- Select Revoke to stop the key at once. The audit log records apikey.revoked with by: admin.
- Connected agents lists the agents that members connected with their own sign-in. Select Disconnect to stop one at once. The audit log records oauth.revoke with by: admin.
When you remove a member, ContextOwl revokes their agent keys and connected agents in your organization. A new invite does not bring them back.
Key lifetime
Admins can limit how long an agent key stays valid. Open Admin > Settings > Security > Agent key lifetime and choose 7, 30, or 90 days. The default is No limit, and every plan can set a limit.
- A new key must expire within the limit. A key without an expiry gets 30 days, or the limit when the limit is shorter. A longer expiry returns 400 key_lifetime_exceeded.
- A shorter limit also shortens every live key that lasts longer. Agents that use these keys need a new key before the new expiry.
- The audit log records each change as org.key_policy_updated with the number of keys that it shortened.
Publishing keys
When your organization reviews agent changes, a change from an agent key to content that readers see waits in Admin > Proposals. Turn the review on or off in Admin > Settings > API > Review agent changes. New organizations start with it on.
An admin can approve a key once as a publishing key. Its changes then go live at once, also while the review is on. Approve only keys that you control, such as the key of your GitHub Action, and bind them to one workspace.
- Open Admin > Settings > API.
- Select Approve publishing on the key row in Agent keys or Member keys, or select Publish directly when you create the key.
Each key row shows PUBLISHING KEY or GOES TO REVIEW. Review agent changes lists the publishing keys, and Remove ends an approval. The audit log records apikey.publishing_approved and apikey.publishing_removed. A key without a permission that changes live content needs no approval.
Rotation
Create a replacement key, deploy it to the client, confirm the client works, then revoke the old key. Existing keys show their prefix, permission count, expiry, and last-used timestamp so you can identify stale clients.
What ContextOwl records
When an agent searches, lists, or reads articles with a key, ContextOwl records the tool, the article, how many results a search returned, the key, and the client name the agent reports. An agent can send the question of its user with each search, in the question argument. ContextOwl keeps the search text for 90 days, with the question, so admins can see what agents ask. Tokens and email addresses are removed before the text is saved.
ContextOwl sorts each call by who made it:
- AI agents: MCP clients, assistants such as ChatGPT-User and claude-code, a search that sends question, and any call with the
ContextOwl-Agentheader. - Integrations: cowl and the GitHub Action. When cowl runs inside an agent, such as Claude Code, the call counts as that agent.
- Scripts: curl and other HTTP clients that send no question and name no agent.
To see the data, open Admin > Analytics and scroll to AI agents. It lists what agents asked, the questions your docs didn't answer, the pages agents read next to human reads, and the agents and keys that called in. Who asked splits the section into agent keys, agents without a key, and the agents that signed-in readers connected. A search counts as unanswered when it found no match, or when the agent didn't open any of the top 3 results within 30 minutes. When an agent sends one question with several searches, the question is answered when one of them led to a read. Use Draft on an unanswered question to start a page with that question as its title.
An agent can also tell you about a question that your docs didn't answer with report_content_gap. Next steps on the same page groups these reports with the unanswered searches of people and agents.
To stop saving search text, turn off Record search text in Admin > Settings > API. That also deletes the text and the questions saved so far. Counts stay either way.