Artifacts, projects, MCP and the rest¶
octomate.schemas.artifacts ¶
Owned artifacts; a thread may reference one but does not own its content.
ArtifactSandboxPolicy
pydantic-model
¶
Bases: BaseModel
Public sandbox policy, tied to the embedding console by frame-ancestors.
Sources covering the console hostname are refused, including wildcards and alternate schemes or ports. HTML and invocation data never travel in this policy URL; the authenticated viewer sends them over the sandbox bridge.
Fields:
-
parent_origin(AnyHttpUrl) -
csp(McpAppResourceCSP)
Validators:
Source code in octomate/schemas/artifacts.py
protect_console
pydantic-validator
¶
Source code in octomate/schemas/artifacts.py
Artifact ¶
Bases: BaseTransmuter
A deliverable with its own identity and owner, requiring no thread.
The artifact UUID identifies its viewer independently of any ledger row. Referencing it in a thread does not transfer ownership or grant content access.
Source code in octomate/schemas/artifacts.py
id
class-attribute
instance-attribute
¶
owner_id
class-attribute
instance-attribute
¶
owner_id: UUID7 = Field(
frozen=True,
description="Registered owner; thread participation does not replace this ownership.",
)
title
class-attribute
instance-attribute
¶
title: str = Field(
min_length=1,
description="Display title captured when the artifact is created.",
)
created_at
class-attribute
instance-attribute
¶
created_at: AwareDatetime = Field(
default_factory=lambda: datetime.now(UTC),
description="When this artifact was recorded, in UTC.",
)
McpAppArtifact ¶
Bases: Artifact
An MCP invocation retained for an authorized artifact viewer.
The saved input and result support replay after an authorized UI resource fetch. The invocation's installation UUID never follows namespace reuse, and deleting a thread or uninstalling the provider does not delete it.
Source code in octomate/schemas/artifacts.py
McpAppOverview
pydantic-model
¶
Bases: BaseModel
Saved display metadata for native channel cards, without invocation content.
Fields:
-
artifact_id(UUID7) -
title(str) -
provider_name(str) -
viewer_url(AnyHttpUrl)
Source code in octomate/schemas/artifacts.py
viewer_url
pydantic-field
¶
Absolute viewer link; opening it still requires the owner's login.
McpAppView
pydantic-model
¶
Bases: BaseModel
An authorized artifact snapshot and freshly fetched resource for replay.
Fields:
-
artifact(McpAppArtifact) -
resource(McpAppResource) -
sandbox_origin(AnyHttpUrl) -
sandbox_url(AnyHttpUrl) -
viewer_path(str)
Source code in octomate/schemas/artifacts.py
octomate.schemas.project ¶
UpstreamVariant ¶
RemoteUpstream
pydantic-model
¶
Bases: BaseModel
An upstream whose mirror is made by cloning and kept current by fetching.
Fields:
Source code in octomate/schemas/project.py
DirectoryUpstream
pydantic-model
¶
Bases: BaseModel
An upstream whose mirror is made by git init and kept current by copying
the directory in and committing.
Fields:
Source code in octomate/schemas/project.py
Project ¶
Bases: BaseTransmuter
A project: the roots that are it, and how it is driven.
Every project is declared — the operator's projects: block is the only way in.
A session running where no project claims is recorded under none.
Source code in octomate/schemas/project.py
id
class-attribute
instance-attribute
¶
name
class-attribute
instance-attribute
¶
name: str = Field(
default="",
description="Stable name for this project. Defaults to the root's directory name — `~/Projects/octoverse/inky` is `inky` — and steps aside to `<name>-2` when another root already answers to it.",
)
root
class-attribute
instance-attribute
¶
extra_roots
class-attribute
instance-attribute
¶
extra_roots: list[LocalPath] = Field(
default_factory=list,
description="Further directories that are also this project — a settings tree, a sibling checkout — each an absolute local path.",
)
upstream
class-attribute
instance-attribute
¶
upstream: UpstreamVariant = Field(
description="Where this project's mirror comes from and how it is kept current: a remote is cloned and fetched, a directory is `git init`'d and synced by copying in and committing. Required: where a mirror syncs from is the declaration's to say, not guessed from the root."
)
description
class-attribute
instance-attribute
¶
description: str | None = Field(
default=None,
description="What this project is, for a human reading the registry and for a model choosing between registered projects. Not agent instructions: those live in the project's own `AGENTS.md`/`CLAUDE.md`.",
)
enabled
class-attribute
instance-attribute
¶
enabled: bool = Field(
default=True,
description="Whether this project is part of the working set. Reconciliation clears it for a root that is no longer on disk, so the row survives for the runs and threads that name it while nothing new resolves to it.",
)
roots
property
¶
Every directory that is this project: root, then any extra_roots.
name_from_root ¶
A project with no name of its own is called after its root's directory.
local_path has already refused a root with no name, so there is always one
to take. A name two projects both want is refused by
ProjectManager.reconcile, which is where the names in use are known.
Source code in octomate/schemas/project.py
contains ¶
Whether path is one of this project's roots, or inside one.
Both sides are resolved, because is_relative_to is lexical: a .. and a
symlink are the whole attack surface of a check that compares the string it
was handed. A path that does not exist resolves fine, which is what a write
creating a file needs.
Source code in octomate/schemas/project.py
local_path ¶
A project root, normalized: an absolute local path with a name to go by.
~ is expanded here for the reason ConfigPath exists: pydantic keeps ~/...
literal, and Path("~/x").resolve() yields <cwd>/~/x — a root like that
matches nothing, silently. A relative root is made absolute for the same reason,
since it would otherwise hang off whatever directory Octomate was started in.
A url is refused rather than mangled: Path("file:///srv/x") is a perfectly real
relative path, and it matches nothing. That check runs before the Path is built
because PurePath collapses :// to :/, and the scheme stops being visible.
Having a name is the one thing a root needs that a directory does not, so that everything downstream gets a directory it can call the project by.
The directory is deliberately not required to exist. A row outlives the directory it was declared at — reconciliation disables it rather than deleting it — and this type is what rehydrates every row: refusing a dead path here would make one deleted checkout enough to stop the registry loading at all.
Source code in octomate/schemas/project.py
octomate.schemas.mcp ¶
MCP installations: their auth variants, install requests, authorization results and summaries.
McpAuthorizationResult ¶
McpAuthorizationResult = Annotated[
McpAuthorizationStatus
| McpBrowserAuthorizationPending
| McpDeviceAuthorizationPending,
Field(discriminator="status"),
]
McpAppToolMeta
pydantic-model
¶
Bases: BaseModel
Extract the app URI, including the SDK's legacy spelling.
Unrelated metadata is ignored here and preserved on the original Tool.
Fields:
-
resource_uri(Annotated[AnyUrl, UrlConstraints(allowed_schemes=['ui'])] | None)
Source code in octomate/schemas/mcp.py
resource_uri
pydantic-field
¶
The UI resource advertised by a tool, when present.
McpAppInvocation
pydantic-model
¶
Bases: BaseModel
A completed MCP app call, retained independently of its installation.
The tool declaration and complete result are snapshots: replay needs neither another tool call nor a namespace lookup that could resolve a replacement installation. The UI resource itself is fetched under the viewer's access.
Fields:
-
installation_id(UUID7) -
namespace(str) -
provider_name(str) -
tool(Tool) -
resource_uri(AnyUrl) -
arguments(dict[str, JsonValue]) -
result(CallToolResult)
Source code in octomate/schemas/mcp.py
installation_id
pydantic-field
¶
The original installation's identity, retained after uninstall.
resource_uri
pydantic-field
¶
The UI resource declared by the tool, read through its installation.
arguments
pydantic-field
¶
Original arguments passed to the upstream tool, without clipping.
result
pydantic-field
¶
Complete upstream result, including structured content and metadata.
McpAppResourceCSP ¶
Bases: ResourceCSP
Declared origins, restricted to HTTP(S) and network-only WS(S) sources.
Subdomain wildcards are supported. CSP keywords, credentials, paths, queries, fragments, and directive separators are refused before header construction.
Source code in octomate/schemas/mcp.py
validate_domains
classmethod
¶
Source code in octomate/schemas/mcp.py
McpAppResourceUI ¶
Bases: AppConfig
Resource UI metadata; requested permissions and domains are not grants.
Source code in octomate/schemas/mcp.py
csp
class-attribute
instance-attribute
¶
csp: McpAppResourceCSP | None = Field(
default=None,
description="Validated declared origins for sandbox policy.",
)
McpAppResource
pydantic-model
¶
Bases: BaseModel
A single matching MCP Apps HTML resource, decoded for the sandbox.
HTML is untrusted and must only be rendered by the isolated sandbox. Resource metadata describes requests; the host still applies its own sandbox policy.
Fields:
-
uri(AnyUrl) -
html(str) -
ui(McpAppResourceUI)
Validators:
Source code in octomate/schemas/mcp.py
validate_html
pydantic-validator
¶
NoAuth
pydantic-model
¶
BearerAuth
pydantic-model
¶
Bases: BaseModel
A static bearer token.
Fields:
Source code in octomate/schemas/mcp.py
OAuth
pydantic-model
¶
Bases: BaseModel
OAuth, authorized by the installing user.
Config:
extra:forbid
Fields:
-
kind(Literal['oauth'])
Source code in octomate/schemas/mcp.py
McpAuthorizationStatus
pydantic-model
¶
Bases: BaseModel
The stored grant's status, or null when there is none.
Fields:
-
status(OAuthConnectionStatus | Literal[None])
Source code in octomate/schemas/mcp.py
McpBrowserAuthorizationPending
pydantic-model
¶
Bases: BaseModel
A browser authorization is waiting on the user.
Fields:
-
status(Literal['pending_browser'])
Source code in octomate/schemas/mcp.py
McpDeviceAuthorizationPending
pydantic-model
¶
Bases: BaseModel
A device authorization is waiting on the user; poll again after the interval.
Fields:
-
status(Literal['pending_device']) -
retry_after_seconds(int)
Source code in octomate/schemas/mcp.py
McpInstallRequest
pydantic-model
¶
Bases: BaseModel
What installing an MCP takes: a name, a namespace, an HTTPS endpoint, and either an auth choice or the tentacle that supplies it.
Fields:
-
name(str) -
namespace(str) -
url(HttpsUrl) -
auth(Annotated[NoAuth | BearerAuth | OAuth, Field(discriminator='kind')] | None) -
tentacle_id(str | None)
Validators:
Source code in octomate/schemas/mcp.py
auth
pydantic-field
¶
tentacle_id
pydantic-field
¶
Configured tentacle supplying the MCP and its authentication.
public_endpoint
pydantic-validator
¶
Source code in octomate/schemas/mcp.py
Mcp ¶
Bases: BaseTransmuter
A user's MCP installation, polymorphic on how it authenticates.
Source code in octomate/schemas/mcp.py
NoAuthMcp ¶
BearerMcp ¶
Bases: Mcp
An installation authenticating with an encrypted bearer token.
Source code in octomate/schemas/mcp.py
OAuthMcp ¶
Bases: Mcp
An installation authenticating with the user's OAuth grant.
Source code in octomate/schemas/mcp.py
McpTentacleInfo
pydantic-model
¶
Bases: BaseModel
A configured MCP tentacle as offered for installation.
Fields:
Source code in octomate/schemas/mcp.py
McpOAuthSummary
pydantic-model
¶
Bases: BaseModel
An OAuth installation's grant status and the flows it supports.
Fields:
-
status(OAuthConnectionStatus | Literal['pending_browser', 'pending_device', None]) -
flows(list[OAuthFlowKind])
Source code in octomate/schemas/mcp.py
McpServerSummary
pydantic-model
¶
McpToolCatalog
pydantic-model
¶
Bases: BaseModel
The tools and instructions an installation currently serves.
Fields:
-
instructions(str) -
tools(list[Tool])
Source code in octomate/schemas/mcp.py
tools_by_name
cached
property
¶
Index this discovery snapshot once; refresh creates a new catalog.
octomate.schemas.oauth ¶
OAuth machinery: the cipher, flow payloads, callback transports, and the persisted operation and connection.
OAUTH_START_PATH
module-attribute
¶
OAuthCipher ¶
Encrypts short-lived operation secrets and durable OAuth tokens at rest.
Source code in octomate/schemas/oauth.py
encrypt ¶
OAuthFlowContext
dataclass
¶
The manager's owner-bound input to a connector strategy.
OAuthManager creates it only after UserManager resolves the initiating
channel profile to a registered user. The operation id correlates later device
polling or browser callbacks; it never selects or overrides the owning user.
Source code in octomate/schemas/oauth.py
OAuthDiscoveryState
pydantic-model
¶
Bases: BaseModel
Discovered OAuth server metadata and client registration retained for reuse.
Fields:
-
resource(HttpsUrl | None) -
metadata(OAuthMetadata) -
client(OAuthClientInformationFull) -
scope(str | None)
Source code in octomate/schemas/oauth.py
DeviceAuthorizationResponse
pydantic-model
¶
Bases: BaseModel
The authorization server's response when a device flow starts.
A DeviceAuthorizationFlow returns this internal value to the manager. The manager
adds its operation id before the verification instructions leave the OAuth
boundary; the future completion step polls with server-side operation state.
Fields:
-
verification_uri(HttpsUrl) -
verification_uri_complete(HttpsUrl | None) -
device_code(SecretStr) -
user_code(SecretStr) -
expires_at(AwareDatetime) -
interval_seconds(int)
Source code in octomate/schemas/oauth.py
AuthorizationRequest
pydantic-model
¶
Bases: BaseModel
The provider-facing request that starts authorization-code OAuth.
An AuthorizationCodeFlow builds this after receiving the callback URI.
Its URI may contain OAuth state and must not be sent to a channel directly. The
selected callback transport stages it and returns an AuthorizationLink.
Fields:
-
authorization_uri(AnyHttpUrl) -
code_verifier(SecretStr | None) -
expires_at(AwareDatetime) -
discovery_state(OAuthDiscoveryState | None)
Source code in octomate/schemas/oauth.py
code_verifier
pydantic-field
¶
The PKCE verifier whose challenge the authorization URI carries, returned so the manager can seal it into the operation and spend it at the token exchange. None for a provider that does not offer PKCE.
DeviceAuthorization
pydantic-model
¶
Bases: BaseModel
Device verification instructions returned by the manager.
The channel presents the verification URI and user code to the initiating user. Its operation id lets the later polling and confirmation steps resume the exact owner-bound authorization without accepting a user id from the caller.
Fields:
-
operation_id(UUID7) -
verification_uri(HttpsUrl) -
verification_uri_complete(HttpsUrl | None) -
user_code(SecretStr) -
expires_at(AwareDatetime) -
interval_seconds(int)
Source code in octomate/schemas/oauth.py
OAuthPending
pydantic-model
¶
Bases: BaseModel
A device token exchange that the authorization server has not completed.
The manager returns this when the user has not yet approved the device code.
The channel can ask the same owner to confirm again after retry_after_seconds.
Fields:
-
retry_after_seconds(int)
Source code in octomate/schemas/oauth.py
OAuthGrant
pydantic-model
¶
Bases: BaseModel
Provider credentials returned after the user authorizes an operation.
A device flow or authorization-code flow returns this only to OAuthManager.
The manager encrypts its secrets before persisting the owner-bound connection.
Fields:
-
access_token(SecretStr) -
refresh_token(SecretStr | None) -
token_type(str) -
scopes(list[str]) -
subject(str | None) -
account_label(str | None) -
expires_at(AwareDatetime | None) -
discovery_state(OAuthDiscoveryState | None)
Source code in octomate/schemas/oauth.py
AuthorizationLink
pydantic-model
¶
Bases: BaseModel
The safe authorization-code link returned to the channel.
The link contains only the operation UUID. Opening it makes the direct or relay transport retrieve the staged provider request, redirect the browser, and return the eventual callback to the manager's shared completion boundary.
Fields:
-
operation_id(UUID7) -
authorization_uri(AnyHttpUrl) -
expires_at(AwareDatetime)
Source code in octomate/schemas/oauth.py
OAuthCallbackTransport ¶
Bases: ABC
Moves authorization-code traffic across deployment ingress.
After the manager establishes the owner, the transport supplies the provider's callback URI and stages the secret-bearing authorization request behind a UUID-only link. Direct HTTP and relay delivery converge on the same later manager completion step.
Source code in octomate/schemas/oauth.py
DirectHttpOAuthCallbackTransport ¶
Bases: OAuthCallbackTransport
Authorization-code transport backed by Octomate's own HTTP routes.
base_uri is where a browser reaches this deployment, which is the only thing
the two paths below need to become real URIs. A loopback address serves local
development, where the browser and Octomate are the same machine; a tunnel or
domain replaces it for anyone else, and nothing but this value changes.
Source code in octomate/schemas/oauth.py
callback_uri
async
¶
prepare_authorization
async
¶
Return the UUID-only link, ignoring the provider URI it stands in for.
Staging already happened: the manager sealed that URI into this operation's encrypted payload before asking for a link, and the start route reads it back from there. Nothing crosses a deployment boundary, which is the whole difference between this transport and a relay.
Source code in octomate/schemas/oauth.py
RelayOAuthCallbackTransport ¶
Bases: OAuthCallbackTransport
Authorization-code transport backed by an external callback relay.
Source code in octomate/schemas/oauth.py
OAuthTokenPayload
pydantic-model
¶
Bases: BaseModel
The plaintext token envelope immediately before encryption or after decryption.
Fields:
-
flow(OAuthFlowKind) -
access_token(SecretStr) -
refresh_token(SecretStr | None) -
token_type(str) -
discovery_state(OAuthDiscoveryState | None)
Source code in octomate/schemas/oauth.py
DeviceOperationPayload
pydantic-model
¶
Bases: BaseModel
The plaintext device-authorization envelope immediately before encryption.
A provider mints a fresh code on every start, so an authorization that is still pending can only be shown to its user again out of what was sealed here when it began — nothing but the operation row survives the turn that started it.
Fields:
-
device_code(SecretStr) -
user_code(SecretStr) -
verification_uri(HttpsUrl) -
verification_uri_complete(HttpsUrl | None)
Source code in octomate/schemas/oauth.py
AuthorizationCodeOperationPayload
pydantic-model
¶
Bases: BaseModel
The plaintext authorization-code envelope immediately before encryption.
Everything the browser round trip needs and nothing the browser can be trusted to carry: the state a callback must match, the PKCE verifier the token exchange spends, the redirect URI that exchange has to replay, and the provider URI the start route redirects to. All of it is sealed here because the request that started the authorization is long gone by the time any of it is used.
Fields:
-
state(SecretStr) -
code_verifier(SecretStr | None) -
callback_uri(AnyHttpUrl) -
authorization_uri(AnyHttpUrl) -
discovery_state(OAuthDiscoveryState | None)
Source code in octomate/schemas/oauth.py
serialize_secret ¶
OAuthOperation ¶
Bases: BaseTransmuter
An authorization in flight: the encrypted flow state, its expiry, and the poll interval of a device flow.
Source code in octomate/schemas/oauth.py
OAuthConnection ¶
Bases: BaseTransmuter
A stored grant: the encrypted tokens, their scopes and expiry, and the account they belong to.
Source code in octomate/schemas/oauth.py
octomate.schemas.todos ¶
Conversation-scoped todos and their write payload.
Todo ¶
Bases: BaseTransmuter
One conversation-scoped todo, keyed by its short ref.
Source code in octomate/schemas/todos.py
TodoWrite ¶
Bases: TypedDict
Write-payload for TodoManager.write_todos — one item to (re)create.
Source code in octomate/schemas/todos.py
octomate.schemas.spills ¶
The persisted tool-output spill.
ToolOutputSpill ¶
Bases: BaseTransmuter
One oversized tool return, kept by handle until retention closes over it.