Skills & Tools
Three ways to give your agent new capabilities: tools, skills, and MCP servers. Each fits a different shape of need.
| Mechanism | Best for | Where it runs |
|---|---|---|
| Built-in tools | Filesystem, shell, web | Sandbox container |
| Custom tools | Your own JSON-schema’d action | Sandbox or your endpoint |
| Custom skills | Reusable prompt + reference files | Mounted into sandbox |
| MCP servers | Any MCP-spec capability set | Wherever the MCP server lives |
Built-in tools
Section titled “Built-in tools”The agent_toolset_20260401 toolset ships with: bash, read, write, edit, glob, grep, web_fetch, web_search. Add it to your agent and the model can do filesystem and shell work in the per-session container.
{ "name": "my-agent", "model": "claude-sonnet-4-6", "system": "...", "tools": [ { "type": "agent_toolset_20260401" } ]}web_fetch and web_search route through openma’s outbound proxy, so they work without the sandbox having direct internet access.
Custom tools
Section titled “Custom tools”Define a tool inline on the agent with a JSON schema:
{ "tools": [ { "type": "custom", "name": "lookup_user", "description": "Look up a user by their internal ID.", "input_schema": { "type": "object", "properties": { "user_id": { "type": "string" } }, "required": ["user_id"] }, "execution": { "type": "http", "endpoint": "https://internal.example.com/api/users/lookup", "method": "POST" } } ]}When the model calls the tool:
- The sandbox sends an outbound HTTPS request to your endpoint.
- If the endpoint host is bound to a Vault, the proxy injects the auth header automatically. The model never sees the credential.
- The response is fed back as the tool result.
You can also execute tools entirely inside the sandbox by setting execution: { type: "sandbox", command: "..." }.
Custom skills
Section titled “Custom skills”A skill is a SKILL.md describing the capability, plus any reference files (templates, schemas, examples) the model needs. The platform mounts everything at /home/user/.skills/{name}/ (using the SKILL.md name, not the skill id) and inlines the SKILL.md body directly into the system prompt at session start — no lazy read, no follow-up read tool call to discover what’s there. Format is compatible with Anthropic’s Claude Code skills.
Create a skill
Section titled “Create a skill”In the Console: Skills → New skill. Two API shapes:
# (a) JSON — files inlinedcurl -X POST "$OMA_BASE_URL/v1/skills" \ -H "x-api-key: $OMA_API_KEY" \ -H "content-type: application/json" \ -d '{ "files": [ { "filename": "SKILL.md", "content": "---\nname: invoice-parser\ndescription: Extract structured data from supplier invoices.\n---\n\n# Steps\n1. ..." }, { "filename": "schema.json", "content": "{...}" } ] }'
# (b) Multipart — zip upload (use for large skills with binary files)curl -X POST "$OMA_BASE_URL/v1/skills/upload" \ -H "x-api-key: $OMA_API_KEY" \ -F "file=@./invoice-parser.zip"What goes in SKILL.md
Section titled “What goes in SKILL.md”# Invoice parser
Use this skill when the user uploads a PDF or image of an invoice.
## How to extract
1. Read `/home/user/.skills/invoice-parser/schema.json` for the target shape.2. Use the `pdf` built-in skill to extract text.3. Match fields by label (e.g. "Total Due", "Invoice Number").4. Return JSON matching the schema.
## Examples
See `/home/user/.skills/invoice-parser/example_invoice.pdf` for a reference layout.Attach to an agent
Section titled “Attach to an agent”Skills attach as objects, not bare strings (a bare string array silently doesn’t bind):
{ "skills": [{ "skill_id": "skill_abc123", "type": "custom" }] }On session start the system prompt receives:
<source name="skill:skill_abc123"><skill name="invoice-parser">{full SKILL.md body}</skill></source>and the files mount at /home/user/.skills/invoice-parser/SKILL.md etc.
Built-in skills
Section titled “Built-in skills”Four ship out of the box (type: "anthropic"): xlsx, pdf, docx, pptx. Reference them by id from your agent — no upload needed.
MCP servers
Section titled “MCP servers”Connect any Model Context Protocol server and openma auto-generates an mcp__<server>__<tool> (double underscore) for every capability the server exposes.
{ "mcp_servers": [ { "name": "github", "type": "url", "url": "https://api.githubcopilot.com/mcp/", "authorization_token": "..." } ]}Auth modes — credentials never enter the sandbox:
| Mode | How |
|---|---|
| none | omit authorization_token, no matching vault credential |
| inline bearer | authorization_token: "..." on the server entry |
| vault static bearer | matching auth.type: "static_bearer" credential in a session vault (matched by mcp_server_url host) |
| vault OAuth | matching auth.type: "mcp_oauth" credential — refreshes on 401 and 403 (Airtable/Asana/Sentry use 403 for expired tokens), CAS-writes new token to D1, retries once |
stdio MCP servers run inside the sandbox container: set type: "stdio" with command, args, port. OMA spawns the process, waits for the port to bind, proxies the existing tool wiring at it. Tool discovery is bounded at 15 s per server; up to 20 servers per agent.