One Agent. Shared documents. Explicit control.
dee-agent/0.1-draft · Phase 1 document collaboration. This guide describes the matching source build; check the running deployment’s version and OpenAPI before connecting.
Dee and the service share a small boundary.
Dee holds the Agent identity, its definition and memory documents, conversations, human decisions, and saved document versions. An independently operated Agent Service runs Codex and connects outward to Dee over HTTPS JSON. Local development can use HTTP. No inbound callback, queue, or Dee database access is required.
The first implementation supports one or more independently authorized Agents collaborating on Dee documents. Codex is the first reference engine. Claude adapters, external GitHub/Jira changes, external qualifications, proactive discovery, and multi-Agent scheduling remain later work. Unsupported asset actions are rejected as a whole; a mixed plan does not partially proceed.
The service chooses how to read context, reason, use its native tools, and ask questions. Agent definitions and memory remain ordinary Dee documents. Codex sessions, local runtime records, and credentials remain in the service environment. Dee does not prescribe a model, reasoning effort, prompt template, or business workflow.
Human in Dee → Agent document + discussion + approval
↕ public HTTPS API
Agent Service → Codex session
↕
isolated preparation
Actual document writes → Dee checks approval, current access, control, and revisionCreate and connect an Agent.
Choose Create Agent in your personal area or a Space. A Space administrator manages Agents belonging to that Space. Dee creates the Agent configuration document and linked Definition and Memory documents. The configuration document ID is the stable Agent ID; moving or renaming it does not create a new identity.
Edit the definition with the responsibilities, useful skills or scripts, and relevant document links. On the Agent page choose the response mode, actual scope permission, and definition/memory bindings, then save settings. The initial scope role is viewer and the response mode is mention. Give editing permission when the Agent needs to participate in discussions and approved document work.
Start the separately supplied Agent Service with this Agent ID and the Dee API origin. Open the authorization link it returns, sign in, compare the verification code, and approve as the personal owner or current Space administrator. The Agent page lists authorized connections and last recorded use; neither means that a service is online. Revoke a connection there when it is no longer trusted.
A connection authorizes identity and current permissions, not business plans. The ordinary Dee CLI/MCP connection that acts under a human account remains a separate integration. This protocol uses an independent Agent author and does not impersonate the connecting administrator.
Discuss, confirm, and review the result.
Open a collaboration document, write the desired outcome, and use the mention control to select the Agent. For example, ask it to add acceptance criteria to a release plan. Sending confirms that the message was saved. A processing report appears only when the service actually reports that it is working.
The Agent can reply and discuss freely. Before changing or creating a target document, it submits a frozen plan describing the intended changes. Review the complete plan and choose Confirm plan or Reject plan. Confirmation requires a real browser user with the appropriate current permissions on every affected asset. A service credential cannot approve a plan.
One confirmation can cover several document changes. The Agent can execute within that plan while the work is active and permissions still allow it. A larger or different scope needs a replacement plan and a new human decision. The discussion retains the plan, decision, factual reports, and returned saved-version links.
The service may update the body of an existing memory document explicitly bound to that Agent without a separate plan. It cannot use this exception to create or rename documents, modify its definition, update shared business semantics, or bypass the current work control and version checks.
Stop and start again with current context.
Any current human editor of the collaboration document can stop the whole work rooted at a particular main discussion message. They do not need permission on every asset in the plan. Other work roots are independent.
Stop requested means that Dee recorded the command. It does not claim that every in-flight operation has already stopped. The service stops preparation, tools, child execution, new writes, and memory updates; it reconciles in-flight results and reports waiting while a result remains unknown. It reports stopped only after it has actually stopped.
Only a real editor can choose Start again. This increments the work control revision and begins from current documents, discussion, and existing results. An old native execution cannot merely adopt the new revision and continue. The service must first isolate or reconcile old work. History and completed results remain intact.
The UI shows each Agent’s last accepted report and its timestamp. A report from before the current control revision is marked as an earlier report. No new report, a slow response, or a lost connection is not evidence of failure, completion, or stopped execution.
Run the separately supplied Codex reference service.
From the reference service source checkout, use Node.js 22.13 or newer within the 22.x line and Codex CLI 0.146.0. The checked implementation uses only Node built-ins, including SQLite. It has no inbound listener or npm runtime dependencies. Native sandbox verification targets macOS and Linux.
Copy the example configuration, set dee_url to this deployment’s API origin and agent_id to the Agent configuration document ID, then authenticate Codex inside the service’s dedicated native home. An optional codex.model or codex.effort selects a native engine setting; otherwise the native default applies. One process owns one Agent state directory.
connect prints the normal browser authorization URL and verification code. After a human approves that connection, status verifies the Agent identity and npm start consumes work. Keep the state directory private: it contains the retained credential, durable operation journal, and native sessions. Each command accepts --config with an absolute configuration path.
{
"dee_url": "https://api.dee.cool",
"agent_id": "<Agent configuration document ID>",
"state_dir": ".state",
"codex": {
"binary": "codex"
}
}cp service.example.json service.local.json
# Edit service.local.json with the API origin and Agent ID.
mkdir -p .state/native-home/.codex
CODEX_HOME="$PWD/.state/native-home/.codex" codex login
node src/cli.mjs connect
node src/cli.mjs status
npm startnpm run check
npm test
npm run smoke:codex
# Revoke the Dee connection when it is no longer needed.
node src/cli.mjs disconnectAuthorize one independent identity per credential.
Use https://api.dee.cool as the API origin for this build. A client generates two independent 32-byte base64url random secrets. Keep the device secret and plaintext credential private locally; send only the credential’s SHA-256 hash to POST /agent/login/start. Add subject: {kind: "agent", agent_id}. Omitting subject preserves the ordinary human-account connection.
The start response contains the request ID, verification code, verification URL, and expiry. Open that URL for the owner or Space administrator. Poll POST /agent/login/poll with the original request ID and device secret. The approved Agent result has actor: {kind: "agent", agent_id}, connection_id, and expires_at: null. Reject an incompatible actor shape; never fall back to a human identity.
Send the retained credential as Authorization: Bearer and bind requests with X-Dee-Expected-Agent-Id. Agent connections persist until explicitly revoked. Every request still checks current scope and permissions. GET /api/agents/me identifies the Agent, protocol version, connection, and saved configuration. POST /agent/logout revokes this connection. Never put credentials in definition or memory documents.
Human configuration, connection management, decisions, and work controls use the signed-in browser and the expected account header. Browser mutations require the configured application Origin. Connecting a service is distinct from approving a plan.
Human management writes recheck the original browser session after storage waits and immediately before commit. An expired session cannot authorize a new connection or configuration change. Sign in again and recover the original request using its receipt.
{
"device_secret": "<locally generated device secret>",
"credential_sha256": "<SHA-256 of a separate locally retained credential>",
"client_name": "Organization Agent Service",
"subject": {
"kind": "agent",
"agent_id": "<Agent configuration document ID>"
}
}Read context and communicate using existing resources.
The Agent ID is the configuration document ID. The work key is {document_id, root_message_id}; root_message_id is the initial main message and remains stable even if its content is deleted. A Codex session ID is local runtime state, not a Dee identity or work key.
GET /api/agents/me/documents lists currently readable documents in the Agent’s scope. Read current documents and individual saved revisions, messages, message context, and threads; search through POST /api/search. Use /api/agents/me/documents for the scoped collection. Revision-history lists/diffs, document source helper endpoints, resources, and unrelated account APIs are not part of independent Agent access in Phase 1. Personal scope covers documents held by the owner; Space scope covers that Space. Direct grants merge with scope permissions but do not enlarge the Agent’s scope. Read the current definition and memory bindings under those same permissions.
Send ordinary messages through POST /api/documents/{document_id}/messages, using the existing parts and reply_to fields. Both send and edit accept agent_mentions. Auth determines author; clients cannot self-assign authors or protected agent_record values. A document editor can mention a Space Agent without being a member of the Space.
The Agent judges the actual output’s disclosure boundary. Generic advice need not expose every document the Agent has ever read. It must not disclose inaccessible internal facts. Dee enforces resource access and supported explicit reference checks. The optional disclosure-check endpoint checks specified source documents against a target; it is not a required preflight for every message.
Use the plan as the write authority.
POST /api/documents/{document_id}/agent-plans freezes the plan Markdown, executor Agent IDs, and changes. Each change has a stable ID and either an existing Dee document target or an explicit creation origin and parent. Include the current expected_control_revision. The returned plan_id is also the protected plan message ID. Replacement plans invalidate the old plan atomically and do not inherit its approval.
The browser confirmation card shows every frozen executor Agent identity and the personal holder or Space and parent of each creation target. Review those structured fields together with the plan text. A definite first business rejection releases that action so an editor can choose again, including rejecting a plan they cannot approve. A lost response keeps the original operation recoverable; a later missing receipt or retry rejection does not replace that original intent.
Read GET /api/documents/{document_id}/agent-plans/{plan_id} for the frozen snapshot, current human decision, control, execution blockers, and known created-document bindings. Execution allowed is specific to the reading Agent: overall approval and control must hold, and the Agent must be able to operate at least one change. It does not grant permission for the other changes; every write checks its selected target. A human reader receives permission_unavailable for execution; this does not mean that the human is ineligible to confirm.
After a real browser decision, use ordinary document create/save with agent_context. It identifies the collaboration work, current control revision, and plan_id, decision_id, change_id, and qualification_id: null. Save also supplies the current expected_revision_id. The actual Dee write transaction verifies the current Agent, permissions, active control, unchanged approval, target and executor, and document revision.
Each approved create change binds at most one actual document. Replaying the original operation returns its original receipt. A second operation cannot create a second document from that same item; subsequent saves may continue on its bound document within the approved scope. A stale document revision never silently overwrites a human edit.
A memory-body save uses authorization: {kind: "memory"} with the same work and control fields. Only existing, independent memory bound to that Agent qualifies. The title stays unchanged. Definition/memory bindings are mutually exclusive, and one memory document cannot be assigned to multiple Agents.
{
"agent_context": {
"document_id": "<collaboration document>",
"root_message_id": "<main message>",
"control_revision": "0",
"authorization": {
"kind": "plan",
"plan_id": "<approved plan>",
"decision_id": "<current human approval>",
"change_id": "<matching plan item>",
"qualification_id": null
}
}
}Report what happened, not what is assumed.
PUT /api/documents/{document_id}/threads/{root_message_id}/agent-feedback/{agent_id} records the authenticated Agent’s latest report for that work. Supply operation_id, expected_revision, control_revision, state, and a brief factual Markdown report. The first feedback revision is 1; the initial expected revision is 0, both encoded as decimal strings.
States are processing, waiting, completed, stopped, and failed. Processing/completed require active work; stopped requires stopped work; waiting/failed are valid in either control state. The feedback control revision must match current control. Revisions prevent late reports from overwriting newer work.
GET returns the latest accepted feedback together with current control in the same read snapshot. A report can belong to an older control revision. Timestamps record server acceptance, not liveness. Completion applies to this Agent’s report, not automatically to the entire multi-Agent work.
Plan, decision, control, and feedback records create protected discussion logs. The service consumes the corresponding typed agent_* event; the message with agent_record is a presentation of that same fact. It must not trigger a second model turn or repeat an asset operation. Feedback itself does not create new work.
Recover from current facts and original receipts.
Use GET /api/agents/me/changes with cursor, max_events, and wait_ms. Bootstrap or a reset gives a fence before current reads. Read the current configuration, scoped documents and discussions, then continue from that fence. Deduplicate event IDs. For a protected log, its agent_record.read_url can rebuild the current plan/control/feedback fact.
Persist received inputs, cursor, native session association, current control revision, complete outgoing requests and operation IDs before dispatch, and returned receipts. Coordinate consumption of a work key in the service. Reopening a session does not by itself authorize replaying a side effect.
If a response is lost, inspect GET /api/agents/operations/{operation_id} for the original protocol result; document and message operations use their existing receipt endpoints. Retry the exact original request when appropriate. Keep the same actor, operation ID, and complete input. A missing receipt or network error means unconfirmed, not failed or unexecuted.
A conflict requires reading the relevant current fact. Never replace a human decision, control revision, or document revision merely to make an old request pass. After stop/restart, reconcile prior effects and read the latest context before new execution. Revocation and permission loss block new operations while retaining historical authors and decisions.
Controlled isolated preparation may create drafts, code, and tests. The service must keep target writes behind the approved tool boundary, including subprocesses and child agents. Prompts alone do not enforce this. Phase 1 exposes actual target writes only to Dee documents; external asset writes remain unsupported.
Find the complete interfaces and schemas.
Use the linked OpenAPI as the source of complete request/response schemas, including existing document, message, revision, pagination, changes, and error dependencies. Agent authorization appears in the API guide’s runtime protocol supplement. Paths below are the operations declared by this source build, with full paths rather than aliases.
JSON uses snake_case. IDs encode an unsigned 128-bit value with the alphabet ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789, left-padded with A to 22 characters. Reject values above 2^128−1; a numeric-looking 22-character string is not necessarily valid. Configuration revisions are nonnegative JavaScript-safe integers. Control and feedback revisions and event positions are lossless decimal strings. Business times are Unix milliseconds; login and connection metadata use Unix seconds. Required nullable fields remain present as null. Unknown request fields are rejected.
List endpoints use page_index, page_size, and comma-separated order_by. Configuration/body revisions are independent. Original operation receipts establish that the original action occurred; they do not establish current permission or execution authority. Errors carry name, message, and data, with the HTTP status and x-request-id available for diagnosis.
GET /api/agents/meGET /api/agents/me/changesPOST /api/agents/me/disclosure-checkGET /api/agents/me/documentsGET /api/agents/operations/{operation_id}GET /api/agents/{agent_id}PUT /api/agents/{agent_id}GET /api/agents/{agent_id}/connectionsDELETE /api/agents/{agent_id}/connections/{connection_id}GET /api/communication/operations/{operation_id}POST /api/documentsGET /api/documents/operations/{operation_id}POST /api/documents/{document_id}/agent-plansGET /api/documents/{document_id}/agent-plans/{plan_id}POST /api/documents/{document_id}/agent-plans/{plan_id}/decisionsGET /api/documents/{document_id}/agentsPUT /api/documents/{document_id}/collaborators/agents/{agent_id}DELETE /api/documents/{document_id}/collaborators/agents/{agent_id}GET /api/documents/{document_id}/threads/{root}/agent-controlPUT /api/documents/{document_id}/threads/{root}/agent-controlGET /api/documents/{document_id}/threads/{root}/agent-feedback/{agent_id}PUT /api/documents/{document_id}/threads/{root}/agent-feedback/{agent_id}GET /api/documents/{id}PUT /api/documents/{id}GET /api/documents/{id}/messagesPOST /api/documents/{id}/messagesGET /api/documents/{id}/messages/{message_id}PUT /api/documents/{id}/messages/{message_id}DELETE /api/documents/{id}/messages/{message_id}GET /api/documents/{id}/messages/{message_id}/contextGET /api/documents/{id}/revisions/{revision_id}GET /api/documents/{id}/threads/{thread_id}POST /api/searchVerify the same public path used by external services.
Use the independently supplied reference service source and its README for its actual install command, configuration, Codex compatibility, and verification entrypoint. This page does not invent a published package or repository address. A matching deployment and a real, authenticated Codex installation are needed for the live engine check.
Create an Agent, bind its definition and memory, grant explicit editing permission, connect through normal browser approval, and mention it in an existing document. Observe a real reply and processing report. Ask for a small change, confirm its frozen plan in the browser, and verify the actual saved version and Agent author.
Repeat with rejection, a replaced plan, a concurrent human save, revoked credentials, stop before saving, and start-again with changed context. Drop a save/create response and restart the service: it must recover the original receipt and produce no duplicate version or document. Confirm that stopped acceptance is not shown as actual stopped execution.
Also verify one approved document creation, continued saving of its bound result, and an existing own-memory body update. The same tests use ordinary public APIs; our service has no private bootstrap, direct database path, or privileged write bypass. Schema publication or mock tests alone do not demonstrate a successful live Codex run.
Start your first document.
Add your notes, save a first version, and invite a collaborator when you are ready.
Start with a document