The object model in one screen
- 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.
- 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.
- 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.
- 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).
- 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.
- Billing and usage meter all of the above: a plan, a credit wallet, usage breakdowns and cost tags (Billing and usage).
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:<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_whoamireturns 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,sandboxesorskills), 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 withdelete,revoke,archiveorrebuild) needconfirm: true; ask the person first.updateSkillTrustProfilealso needsconfirm: 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 namedolyros://docs/<page>.
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, notRuntime X). The Dockerfile is your job: read the project’spyproject.tomlorpackage.jsonand write theFROMandRUNlines; 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;kindisallby default and narrows toagents,sandboxesorrouters.upload_skill_bundle(files, skill_id, dry_run, display_name, change_note)validates and uploads a skill bundle:filesis the skill folder as a list of{path, content}text files and must includeSKILL.md; paths are relative to the folder (references/x.md,scripts/run.py,olyros.yaml). Call it withdry_run: truefirst and fix everyerrorsentry; warnings do not block. Withoutskill_ida new skill is created (version 1, named bydisplay_nameor the frontmattername); with it a new version of that skill is written (same frontmatternamerequired,change_notekept on the version; an identical bundle is a no-op withcreated: false). Needsskills:writeand an admin member. Limits: 64 files, 256 KB per file,SKILL.md64 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 inolyros.yaml, so the skill runs withtoolAccess: declared. The result is the shape the browser upload returns:ok,dry_run,created,errorsandwarnings(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 withok: falseanderrors, 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,filesas[{path, content}]withSKILL.mdfirst,file_countandbundle_bytes; withoutversion_idit is the skill’s latest version. Needsskills: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 withskill_id.
Build a skill from this repository
A skill is aSKILL.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:
-
olyros_whoami: the connection must holdskills:writeand the person must be a company admin (skill.manage);agents:readlets you find the agent to bind to yourself. -
olyros_docs("skills"): read the frontmatter rules, the bundle limits, the packages the sandbox image ships and the trust profile before writing anything. -
Write
SKILL.mdfrom what the repository tells you. Frontmatter:name(lowercase kebab-case, at most 64 characters, theolyros-prefix is reserved) anddescription(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 underout/. Put longer material underreferences/and scripts underscripts/as*.py(Python 3.12) or*.js,*.mjs,*.cjs(Node 22). Scripts read only from/work/inand 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. -
If a script calls one of the agent’s tools through the bridge (the
olyrosclient package:from olyros import toolsthentools.<name>(...), orfrom olyros.mcp import <slug>then<slug>.<tool>(...)), addolyros.yamldeclaring every tool it calls:With this file the skill runs withtoolAccess: declared(these tools and nothing else) and a run is refused when the agent lacks one of them; without it the default isagent(everything the agent has).bridgeStub(kind, name, language)underskills:readreturns the exact function the sandbox client exposes for one tool (kindtool,mcporbuiltin;nameis the tool name, or<slug>/<tool>for an MCP tool;languagepythonornode); itsdeclarationis the TypeScript declaration for Node stubs and is empty for Python. Theolyros.yamlline is the tool name undertools:or<slug>: [<tool>]undermcp:, spelled exactly as the catalog returns them. -
upload_skill_bundle(files, dry_run: true): fix everyerrorsentry (code,message,path,line) and call again untilokistrue. Read thewarnings(DEPENDENCY_NOT_IN_IMAGE,NETWORK_CALL,BRIDGE_UNDECLARED_TOOL,FILE_UNREFERENCED, …) and fix what you can; they do not block. -
upload_skill_bundle(files, display_name): the result holdsskill_id,version_idandversion_no1. Keepskill_id. -
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. -
olyros_graphqlwithbindSkillToAgent(agentId, skillId, input: {pinnedVersionId: null}): a null pin follows the skill’s latest version;environmentOverrides(web_chat,slack) andinvocationOverride(model,user,both) narrow where and by whom it is invoked. -
olyros_graphqlwithagentSkills(agentId): check that your binding is listed with an emptymissingTools(tools the skill text names that the agent lacks) and that everybridgeToolsentry your scripts call hasstatusok; amissingstatus means the agent does not mount that tool or MCP server, whichmissingToolsdoes not report. The person tests the skill in the editor’s Chat tab or in a conversation with the agent. -
Leave the trust profile alone unless the person asks for a change. The effective
defaults are
toolAccessdeclaredwitholyros.yaml(elseagent),writesask(the person answers a consent card before a writing tool call),networkbridgeandsecretsnone. When the person wants a different setting, callupdateSkillTrustProfile(skillId, input: {toolAccess, writes, network})withconfirm: true; without it the call is refused withCONFIRM_REQUIRED, and with it the change is listed under the connection on the Agent access page.
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:
-
olyros_whoami:skills:writeand an admin member, as above. -
olyros_graphqlwithmcpServers { id slug displayName description url authMode toolCount allowedTools isActive skillCodeEnabled }: pick the server. Note itsslug(the name yourolyros.yamland scripts use) and itsallowedTools(nullmeans every discovered tool is allowed; otherwise only those names may be called). IftoolCountis0, ask the person to open the server’s page and run Discover tools; you cannot discover. IfskillCodeEnabledisfalse, ask an admin to allow skill code to call the server (the skill-code switch on its page); a run would otherwise be refused. -
olyros_graphqlwithmcpServerTools(mcpServerId) { name description inputSchema access skippedReason }: the catalog.inputSchemais the JSON schema of each tool’s arguments,accessisreadorwrite(a write asks the person for consent at run time under the default trust profile), and a tool with askippedReasonhas no stored schema and cannot be called from code. -
olyros_graphqlwithbridgeStub(kind: "mcp", name: "<slug>/<tool>", language: "python")(or"node") for each tool the scripts will call:sourceis the exact function signature the sandbox client exposes,declarationthe TypeScript declaration for Node stubs (empty for Python),accessthe read or write class. -
Write the bundle:
SKILL.mdwhosedescriptionnames 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.mdwith 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 underin/, callfrom olyros.mcp import <slug>then<slug>.<tool>(...), and write results underout/; andolyros.yaml:Use<slug>exactly asmcpServersreturned it and the tool names exactly asmcpServerToolsreturned them. -
upload_skill_bundle(files, dry_run: true): fix everyerrorsentry; aREQUIRES_UNKNOWN_TOOLwarning means a declared name is not in the server’s catalog, andBRIDGE_UNDECLARED_TOOLmeans a script calls a toololyros.yamldoes not declare. -
upload_skill_bundle(files, display_name): keepskill_id. -
olyros_graphqlwithagentMcpServers(agentId) { mcpServerId isActive }: the agent that will run the skill must mount the server withisActive: true; if it does not, ask the person to bind the server on the agent’s MCP servers tab, which you cannot do. -
olyros_graphqlwithbindSkillToAgent(agentId, skillId), thenagentSkills(agentId)as in the previous walk-through: everybridgeToolsentry for the server must havestatusok(missingmeans the agent does not mount the server, step 8).
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 theError 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, orupdateSkillTrustProfile, was called withoutconfirm: 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 emptyfileslist, more entries thanSKILL.mdplus 64 files, an empty path or one over 255 characters, content that is not valid text, askill_idthat is not a UUID,display_namegiven withskill_idorchange_notegiven 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,mcpServersand the sandbox queries return ids and names;list_agentsdoes 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_schemashows only what the connection’s scopes allow and never shows excluded operations; areadscope 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; theconfirm flag exists so that the
question is asked.