Skip to main content
Olyros is a workspace where a company runs AI agents on its own terms. It uses its own model keys, its own machines or a managed cloud, its own Slack, GitHub and Jira, and its own rules about who may talk to which agent. This page is written for a coding agent (Claude Code or any other MCP client) that a person has pointed at their company’s Olyros account so that the agent can set things up for them: connect a machine, describe a runtime image, create or clone an environment, inspect what runs where, build a skill and bind it to an agent. It says what the objects are, how to connect, which scopes a connection can hold, which tools exist, and what an agent can never do. The other pages on this site describe each product area in full; read the one for the area before you change anything in it.

The object model in one screen

  1. A company is the tenant: every object below belongs to exactly one company, and a person reaches a company through a membership with a role (Viewer, Editor, Admin). Company settings, users and roles.
  2. Integrations connect the company to outside systems and hold the credentials: model providers (the keys every agent runs on), GitHub, Jira, Slack, remote MCP servers and custom HTTP APIs. Integrations and its per-kind pages.
  3. Agents are the assistants people talk to. Three kinds share one model: a chat agent (Agents), a persistent sandbox with its own working directory and repositories (Sandboxes), and a router, one Slack app that forwards each person to their agent (Routers). Agents draw on tools, MCP servers, skills and memory.
  4. Automation makes agents work without a person typing: workflows react to Jira, GitHub, webhook and agent events (Workflows); schedules fire on a cadence (Schedules); both, and people, create cloud tasks, one-shot units of work with an executor and a result (Cloud tasks and executors).
  5. Execution decides where and in what a task or sandbox runs: an OHO (Olyros Home Orchestrator) machine the company connects, the Olyros Cloud pool, or the company’s own GCP project, and a runtime image (called an environment in the API) with a Dockerfile, env vars and secrets (OHO machines and environments). Executors describe how the model loop runs.
  6. Billing and usage meter all of the above: a plan, a credit wallet, usage breakdowns and cost tags (Billing and usage).
How they relate: an agent runs on a provider integration’s key. A sandbox is an agent plus a venue (an OHO or a cloud backend) plus a runtime image. A router has routes to agents and sandboxes and no model of its own. A task is placed on a backend (the agent’s pin, else the company default, else any backend) and runs inside a runtime image through an executor.

How to connect an agent

Olyros exposes one hosted MCP endpoint over HTTP. An agent authenticates with an agent connection token that a member of the company creates under Settings -> Agent access in the Olyros client app and hands to the agent (Agent access describes that page). The connection acts as that person: it carries a set of scopes (below), and inside every operation the person’s role still applies, so a Viewer’s connection only reads even when it holds a write scope. Tokens are shown once, expire after 30, 90 or 180 days, can be re-issued for the same connection when lost (New token), and can be revoked at any time by the company. Claude Code:
Any other MCP client that reads a JSON configuration:
Replace <token> with the connection token. The endpoint above is the hosted Olyros service; a company on its own deployment reads the exact endpoint from the connection’s mcpUrl, which the Agent access page fills into both snippets. The first call in every session should be olyros_whoami: it returns the connection’s name, company, scopes and expiry, the role and abilities of the person it acts for, the documentation URL and the server version. Read the relevant documentation page (through olyros_docs or this site) before you change anything, and ask the person before any destructive call.

Scopes

A scope is <domain>:<access> for one of six domains. write implies read. A connection holds any subset of these twelve; a call that needs a scope the connection lacks is refused with the name of the missing scope, so you can tell the person what to grant. Everything outside these six domains (users and roles, billing, integrations and their credentials, Slack, tools, workflows, schedules, memories, usage, cost tags, platform administration) is not reachable through an agent connection at all. MCP servers can be read (the catalog), not managed.

Tools

Four generic tools cover the whole surface:
  • olyros_whoami returns the connection (name, company, scopes, expiry, last use), the person it acts for (role and abilities), the documentation URL and the server version. Call it first.
  • olyros_schema(domain) returns the GraphQL schema for one domain (agents, environments, executors, oho, sandboxes or skills), cut down to what the connection’s scopes allow. Read it before composing a query.
  • olyros_graphql(query, variables, confirm) runs one GraphQL operation. Queries and mutations only, one operation per call. Destructive mutations (names starting with delete, revoke, archive or rebuild) need confirm: true; ask the person first. updateSkillTrustProfile also needs confirm: true, because it changes what a skill’s code may do.
  • olyros_docs(page) returns one documentation page as markdown, or the list of pages when called without a page. The same pages are available as MCP resources named olyros://docs/<page>.
Five curated tools cover the common asks without composing GraphQL:
  • create_runtime_environment(name, dockerfile, env_vars, build_args, secrets, description) creates a Docker runtime image. Names use letters, digits, hyphens and underscores only (runtime-x, not Runtime X). The Dockerfile is your job: read the project’s pyproject.toml or package.json and write the FROM and RUN lines; Olyros validates and stores it, returns warnings for lines the runtime will override (ENTRYPOINT, CMD, USER, VOLUME), and builds the image on first use.
  • clone_runtime_environment(source_name, new_name, add_env_vars, dockerfile_append) copies an existing runtime image by name, merges extra env vars and appends text to the copied Dockerfile. Secrets are carried over on the server; you never see their values.
  • list_agents(kind) lists the company’s agents, sandboxes and routers in one answer, with status and counts; kind is all by default and narrows to agents, sandboxes or routers.
  • upload_skill_bundle(files, skill_id, dry_run, display_name, change_note) validates and uploads a skill bundle: files is the skill folder as a list of {path, content} text files and must include SKILL.md; paths are relative to the folder (references/x.md, scripts/run.py, olyros.yaml). Call it with dry_run: true first and fix every errors entry; warnings do not block. Without skill_id a new skill is created (version 1, named by display_name or the frontmatter name); with it a new version of that skill is written (same frontmatter name required, change_note kept on the version; an identical bundle is a no-op with created: false). Needs skills:write and an admin member. Limits: 64 files, 256 KB per file, SKILL.md 64 KB, 4 MB unpacked, about 900 KB of text per call (the request body is capped at 1 MiB; bigger bundles go through the browser upload). Declare the tools the scripts call in olyros.yaml, so the skill runs with toolAccess: declared. The result is the shape the browser upload returns: ok, dry_run, created, errors and warnings (entries {code, message, severity, line, path}), manifest, files ({path, kind, size_bytes}), skill_id, version_id, version_no, file_count, bundle_bytes. A bundle that fails validation is a result with ok: false and errors, not a refused call.
  • download_skill_bundle(skill_id, version_id) returns one skill version as text files: skill_id, skill_name, version_id, version_no, files as [{path, content}] with SKILL.md first, file_count and bundle_bytes; without version_id it is the skill’s latest version. Needs skills:read; the download is recorded in the company’s audit trail. To change an existing skill, download it, edit the files and upload them as a new version with skill_id.

Build a skill from this repository

A skill is a SKILL.md document, optionally with reference files and small Python or Node scripts, that a chat agent loads when a request matches and whose scripts it runs in a disposable sandbox (Skills describes the format, the sandbox and the trust profile in full). The steps, one call each:
  1. olyros_whoami: the connection must hold skills:write and the person must be a company admin (skill.manage); agents:read lets you find the agent to bind to yourself.
  2. olyros_docs("skills"): read the frontmatter rules, the bundle limits, the packages the sandbox image ships and the trust profile before writing anything.
  3. Write SKILL.md from what the repository tells you. Frontmatter: name (lowercase kebab-case, at most 64 characters, the olyros- prefix is reserved) and description (at most 1024 characters, saying what the skill does and when to use it); the body says how to run each script, with the exact command (python scripts/run.py in/x.json out/y.md), its arguments and what lands under out/. Put longer material under references/ and scripts under scripts/ as *.py (Python 3.12) or *.js, *.mjs, *.cjs (Node 22). Scripts read only from /work/in and the skill folder, write only to /work/out, use only the packages the image ships, and make no network calls of their own: anything outside the sandbox goes through the tool bridge. Text files only, no .env, key or certificate files, paths at most four segments deep.
  4. If a script calls one of the agent’s tools through the bridge (the olyros client package: from olyros import tools then tools.<name>(...), or from olyros.mcp import <slug> then <slug>.<tool>(...)), add olyros.yaml declaring every tool it calls:
    With this file the skill runs with toolAccess: declared (these tools and nothing else) and a run is refused when the agent lacks one of them; without it the default is agent (everything the agent has). bridgeStub(kind, name, language) under skills:read returns the exact function the sandbox client exposes for one tool (kind tool, mcp or builtin; name is the tool name, or <slug>/<tool> for an MCP tool; language python or node); its declaration is the TypeScript declaration for Node stubs and is empty for Python. The olyros.yaml line is the tool name under tools: or <slug>: [<tool>] under mcp:, spelled exactly as the catalog returns them.
  5. upload_skill_bundle(files, dry_run: true): fix every errors entry (code, message, path, line) and call again until ok is true. Read the warnings (DEPENDENCY_NOT_IN_IMAGE, NETWORK_CALL, BRIDGE_UNDECLARED_TOOL, FILE_UNREFERENCED, …) and fix what you can; they do not block.
  6. upload_skill_bundle(files, display_name): the result holds skill_id, version_id and version_no 1. Keep skill_id.
  7. Find the agent: list_agents(kind: "agents") returns ids and names (sandboxes and routers do not load skills), or ask the person which agent to bind.
  8. olyros_graphql with bindSkillToAgent(agentId, skillId, input: {pinnedVersionId: null}): a null pin follows the skill’s latest version; environmentOverrides (web_chat, slack) and invocationOverride (model, user, both) narrow where and by whom it is invoked.
  9. olyros_graphql with agentSkills(agentId): check that your binding is listed with an empty missingTools (tools the skill text names that the agent lacks) and that every bridgeTools entry your scripts call has status ok; a missing status means the agent does not mount that tool or MCP server, which missingTools does not report. The person tests the skill in the editor’s Chat tab or in a conversation with the agent.
  10. Leave the trust profile alone unless the person asks for a change. The effective defaults are toolAccess declared with olyros.yaml (else agent), writes ask (the person answers a consent card before a writing tool call), network bridge and secrets none. When the person wants a different setting, call updateSkillTrustProfile(skillId, input: {toolAccess, writes, network}) with confirm: true; without it the call is refused with CONFIRM_REQUIRED, and with it the change is listed under the connection on the Agent access page.
To ship a change later, download_skill_bundle(skill_id) returns the latest version as files; edit them and call upload_skill_bundle(files, skill_id, change_note), with dry_run: true first. The frontmatter name must stay the same (NAME_MISMATCH otherwise); an unchanged bundle answers created: false and writes no version.

Wrap a third-party MCP server in a skill

A company registers remote MCP servers under Agents -> MCP Servers and discovers their tools (MCP servers). A skill can wrap one such server: SKILL.md tells the agent when to use which tool, and scripts call the tools through the bridge so the data never passes through the model. You read the catalog Olyros already discovered; you never talk to the server yourself. One call per step:
  1. olyros_whoami: skills:write and an admin member, as above.
  2. olyros_graphql with mcpServers { id slug displayName description url authMode toolCount allowedTools isActive skillCodeEnabled }: pick the server. Note its slug (the name your olyros.yaml and scripts use) and its allowedTools (null means every discovered tool is allowed; otherwise only those names may be called). If toolCount is 0, ask the person to open the server’s page and run Discover tools; you cannot discover. If skillCodeEnabled is false, ask an admin to allow skill code to call the server (the skill-code switch on its page); a run would otherwise be refused.
  3. olyros_graphql with mcpServerTools(mcpServerId) { name description inputSchema access skippedReason }: the catalog. inputSchema is the JSON schema of each tool’s arguments, access is read or write (a write asks the person for consent at run time under the default trust profile), and a tool with a skippedReason has no stored schema and cannot be called from code.
  4. olyros_graphql with bridgeStub(kind: "mcp", name: "<slug>/<tool>", language: "python") (or "node") for each tool the scripts will call: source is the exact function signature the sandbox client exposes, declaration the TypeScript declaration for Node stubs (empty for Python), access the read or write class.
  5. Write the bundle: SKILL.md whose description names the server and the asks it serves, with one section per tool saying when to use it, its arguments and the command that runs it; references/tools.md with the catalog (name, description, input schema) so the agent can answer questions without a run; scripts/*.py (or *.js) that take their input as arguments or files under in/, call from olyros.mcp import <slug> then <slug>.<tool>(...), and write results under out/; and olyros.yaml:
    Use <slug> exactly as mcpServers returned it and the tool names exactly as mcpServerTools returned them.
  6. upload_skill_bundle(files, dry_run: true): fix every errors entry; a REQUIRES_UNKNOWN_TOOL warning means a declared name is not in the server’s catalog, and BRIDGE_UNDECLARED_TOOL means a script calls a tool olyros.yaml does not declare.
  7. upload_skill_bundle(files, display_name): keep skill_id.
  8. olyros_graphql with agentMcpServers(agentId) { mcpServerId isActive }: the agent that will run the skill must mount the server with isActive: true; if it does not, ask the person to bind the server on the agent’s MCP servers tab, which you cannot do.
  9. olyros_graphql with bindSkillToAgent(agentId, skillId), then agentSkills(agentId) as in the previous walk-through: every bridgeTools entry for the server must have status ok (missing means the agent does not mount the server, step 8).
For a server whose authMode is oauth_per_user, each person who runs the skill must have connected their own account under Settings -> Connected Accounts; the first run asks them. What you cannot do here: register, change, discover, delete or connect to an MCP server, change its allowed tools or its skill-code switch, bind it to an agent, or see who is connected to it and with what. Those stay with the people in the client app.

Limits

The endpoint bounds what one connection can do per minute. These are not tool errors but HTTP answers, so your MCP client reports them as transport failures: Wait for Retry-After and send the call again; do not retry in a tight loop. Keep queries small and paginate lists through their limit and offset arguments where the schema offers them.

How calls are refused

A refused call returns a tool error whose text carries a code (after the Error executing tool <name>: prefix the MCP library adds), so you can act on it:
  • SCOPE_REQUIRED: the connection lacks the named scope. Tell the person what to grant.
  • UNKNOWN_FIELD: the operation is outside the six domains. There is no scope for it.
  • FIELD_EXCLUDED: the operation is never available to agent connections (next section).
  • CONFIRM_REQUIRED: a destructive mutation, or updateSkillTrustProfile, was called without confirm: true.
  • SUBSCRIPTION_NOT_ALLOWED, MULTIPLE_OPERATIONS, INVALID_GRAPHQL: the document itself is not accepted; send one query or mutation.
  • UNKNOWN_DOMAIN, UNKNOWN_PAGE, NOT_FOUND, AMBIGUOUS_NAME: a tool argument did not match; the message lists what would.
  • INVALID_NAME: a runtime image name breaks the rule (letters, digits, hyphens and underscores only, no spaces, up to 100 characters); nothing was created.
  • INVALID_INPUT: a skill bundle tool argument is malformed: an empty files list, more entries than SKILL.md plus 64 files, an empty path or one over 255 characters, content that is not valid text, a skill_id that is not a UUID, display_name given with skill_id or change_note given without it, or either text over 8192 characters. Nothing was validated or written.
  • RATE_LIMITED: skill bundle uploads and downloads are limited to 60 per company per hour, shared with the browser; try again later.
  • CONFLICT: another write to the same skill got in the way of the upload; call again.
  • GRAPHQL_ERROR: the operation ran and the server refused it, most often because the person’s role does not allow it (“Editor or admin role required”).

Common questions

  • How do I find an id? Query the list first: environments, agents, executors, ohoInstances, skills, mcpServers and the sandbox queries return ids and names; list_agents does the same for agents, sandboxes and routers. Objects of another company answer “not found” like unknown ids.
  • A write failed with “Editor or admin role required”. The person behind the connection is a Viewer. Tell them which role the operation needs; a wider scope does not help.
  • Can I read a secret I set? No. Environment and sandbox overlay secrets are write-only for every connection; queries return key names only.
  • Can I see what I did earlier? Every mutation you run, every bundle upload and every bundle download is written to the company’s audit trail and shown under the connection on the Agent access page; other reads are not recorded.
  • Why does the schema miss a mutation I know exists? olyros_schema shows only what the connection’s scopes allow and never shows excluded operations; a read scope hides every mutation of that domain.

What an agent cannot do

An agent connection never reads a secret value. It can set environment secrets and sandbox overlay secrets and see their key names, but the operations that reveal a stored value, that rotate an OHO’s device credentials or that look up a pending OHO registration by its token are excluded for every connection, whatever its scopes. It cannot connect, verify, cap or revoke a bring-your-own Google Cloud backend, because those operations carry integration credentials. It cannot change who may talk to an agent (the Access table) or an agent’s Slack reply options. It cannot subscribe to live events, run more than one operation per call, or reach anything outside the six domains: users, invitations, roles, billing, integrations, Slack, tools, workflows, schedules and platform administration stay with the people in the client app. It can read the company’s MCP servers and their tool catalogs but cannot register, change, discover, delete or connect to one, and never sees who is connected to a server or with what. It cannot grant a tool consent for a skill run (people answer consent cards in chat); it can only revoke one. It cannot exceed the role of the person it acts for. And it should not delete, revoke, archive or rebuild anything, or change a skill’s trust profile, without telling the person first; the confirm flag exists so that the question is asked.