| name | coral |
| description | Publish agents to Coral Marketplace — handles login, manifest generation, and publishing |
| disable-model-invocation | true |
| allowed-tools | Read, Glob, Grep, Bash(curl *), Bash(open *), Bash(mkdir *), Bash(chmod *), Bash(test *), Bash(git *), Write |
| argument-hint | [login | init [slug] | publish] |
Coral Marketplace — Agent Publishing Skill
This skill handles the full agent publishing lifecycle for Coral Marketplace:
login, manifest generation, and publishing.
Routing
Parse $ARGUMENTS to determine which flow to run:
- If
$ARGUMENTS starts with login → run LOGIN flow
- If
$ARGUMENTS starts with init → run INIT flow (pass remaining args as suggested slug)
- If
$ARGUMENTS starts with publish → run PUBLISH flow
- If
$ARGUMENTS is empty → run SMART mode
Smart Mode (no arguments)
Auto-detect what the user needs and run the appropriate flow(s) in sequence:
-
Check if credentials exist:
!test -f ~/.coral/credentials.toml && echo "HAS_CREDS" || echo "NO_CREDS"
-
Check if coral-agent.toml exists in the project:
!test -f coral-agent.toml && echo "HAS_TOML" || echo "NO_TOML"
Decision:
- If NO_CREDS → run LOGIN flow first, then continue to next check
- If NO_TOML → run INIT flow, then continue to PUBLISH
- If both exist → run PUBLISH flow directly
After each flow completes successfully, continue to the next step automatically. The user should be able to go from zero to published in a single /coral invocation.
LOGIN Flow
Step 1: Check existing credentials
Read existing credentials if present:
!test -f ~/.coral/credentials.toml && cat ~/.coral/credentials.toml || echo "NO_FILE"
If credentials exist, tell the user they are already logged in and show the stored marketplace URL. Ask if they want to re-authenticate or continue. If they want to continue, skip this flow.
Step 2: Resolve marketplace URL
Use this priority:
$CORAL_MARKETPLACE_URL environment variable: !echo "${CORAL_MARKETPLACE_URL:-}"
- Default:
https://marketplace.coralprotocol.ai
Step 3: Open browser
Tell the user:
Opening Coral Marketplace login. To get your API key:
- Log in with your account
- Go to API Keys (account settings)
- Create a new key with the publish scope
- Copy the key — it starts with
coral_ and is shown only once
Open the login page in the default browser:
open "<marketplace_url>/auth/login"
If open fails (e.g., headless server), display the URL and ask the user to open it manually.
Step 4: Collect API key
Use AskUserQuestion to ask the user to paste their API key. The key starts with coral_.
Step 5: Validate the key
Check format: the key must start with coral_ and be at least 20 characters long.
Test the key against the marketplace:
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer <KEY>" "<marketplace_url>/auth/me"
- If HTTP 200: Key is valid. Extract and show the user's display name or email from the JSON response.
- If HTTP 401: Key is invalid or expired. Tell the user and ask them to try again or create a new key.
- If connection error: Marketplace may be unreachable. Warn the user but offer to save the key anyway (it can be verified later).
Step 6: Store credentials
mkdir -p ~/.coral
Write ~/.coral/credentials.toml:
[default]
api_key = "<validated_key>"
marketplace_url = "<marketplace_url>"
Set restrictive permissions:
chmod 600 ~/.coral/credentials.toml
Step 7: Confirm
Tell the user: "Logged in successfully. Credentials saved to ~/.coral/credentials.toml."
If running in smart mode, continue to the next flow.
INIT Flow
Step 1: Check for existing manifest
!test -f coral-agent.toml && echo "EXISTS" || echo "NONE"
If coral-agent.toml already exists, read it and ask the user if they want to:
- Overwrite it completely
- Keep it and skip to publish
If they want to keep it, skip this flow.
Step 2: Analyze the project
Read project files to infer agent metadata. Examine the following:
-
README: Glob for README*, readme* at the project root. Extract project name, description, what the agent does.
-
Package manifests: Glob for package.json, Cargo.toml, pyproject.toml, go.mod, setup.py, setup.cfg. Extract:
- Project name
- Version (use as starting point, or default to "0.1.0")
- Description
- License
- Author / developer name
-
Entry points: Glob for main.py, agent.py, app.py, server.py, index.js, index.ts, main.rs, main.go. These determine the runtime command.
-
Docker support: Glob for Dockerfile, docker-compose.yml, docker-compose.yaml. If found, consider docker runtime.
-
MCP capabilities: Grep source files for patterns like resources, tools, tool_refreshing, prompts to infer capabilities.
-
Git remote: !git remote get-url origin 2>/dev/null || echo ""
Summarize what you found to the user before continuing. Example:
Analyzed your project:
- Detected Python agent with entry point
agent.py
- Found README.md with description
- License: MIT (from pyproject.toml)
- Git remote: https://github.com/user/repo
Step 3: Collect required fields
Use AskUserQuestion to collect fields, presenting inferred values as defaults.
Slug (required):
If $ARGUMENTS contains a second word after init (e.g., /coral init my-agent), use it as the suggested slug. Otherwise derive from the project name (lowercase, hyphens instead of spaces/underscores).
Validate the slug:
- 1-32 characters
- Lowercase alphanumeric and hyphens only:
[a-z0-9]([a-z0-9-]*[a-z0-9])?
- Must start and end with alphanumeric
- No consecutive hyphens (
--)
If the user provides an invalid slug, explain why it's invalid and ask again.
Version: Default to version from package manifest, or 0.1.0.
Description: Use README/package description as basis. Ask user to confirm or revise.
Short description: One-line summary for marketplace listing.
License: Default to license from package manifest, or ask.
Developer name: Default to git user name, package author, or ask.
Runtime command: Based on detected entry point. For Python: ["python", "agent.py"]. For Node: ["node", "index.js"]. For Docker: suggest docker runtime with detected image.
Capabilities: Show any inferred capabilities, ask user to confirm. Common values: resources, tools, tool_refreshing, prompts.
Pricing (optional): Ask if the agent is free or paid. If paid, collect min/max price in USD.
Wallet (optional): Ask for Solana wallet address. Can be skipped.
Step 4: Generate the TOML
Construct the complete Edition 3 coral-agent.toml. Rules:
- Always include
edition = 3
- Always include
[agent] with name, version, description, capabilities
- Always include
[marketplace] with slug and short_description
- Always include at least one
[runtimes.*] section
- Only include
[marketplace.price_per_run] if the user set pricing
- Only include
[marketplace.identity] if the user provided a wallet
- Do not include empty optional fields — omit them entirely
- For the readme field: use the project's README content if available, otherwise write a brief placeholder and note it should be updated
- Use triple-quoted strings (
"""...""") for multiline values like readme
Step 5: Write the file
Write the generated TOML to coral-agent.toml in the project root.
Step 6: Confirm
Show a summary:
Created coral-agent.toml:
- Slug:
<slug>
- Version:
<version>
- Runtime:
<executable or docker>
Review the file and edit if needed.
If running in smart mode, continue to the PUBLISH flow.
PUBLISH Flow
Step 1: Read the manifest
!test -f coral-agent.toml && echo "FOUND" || echo "MISSING"
If coral-agent.toml is missing:
No coral-agent.toml found in the current directory.
Run /coral init to create one, or make sure you're in the right project directory.
Stop.
Read the file contents.
Step 2: Local validation
Validate these rules locally before making a network request (gives faster feedback):
- Edition:
edition = 3 must be present
- Agent section:
[agent] must have non-empty name and version
- Version: Must be valid semver (
MAJOR.MINOR.PATCH, optional pre-release like -beta)
- Marketplace section:
[marketplace] must exist with a non-empty slug
- Slug format: 1-32 chars,
[a-z0-9]([a-z0-9-]*[a-z0-9])?, no consecutive hyphens
- Runtimes: At least one of
[runtimes.executable] or [runtimes.docker] must exist
If validation fails, show ALL errors at once (not one at a time) with fix guidance. Example:
Validation failed:
- Slug
My-Agent is invalid: must be lowercase alphanumeric and hyphens only
- Version
1.2 is invalid: use semver format like 1.2.0
Fix these in coral-agent.toml and run /coral publish again.
Stop if validation fails.
Step 3: Confirm before upload
Show a summary and ask the user to proceed:
Ready to publish to Coral Marketplace:
- Slug:
<slug>
- Version:
<version>
- Name:
<name>
Publish now?
Step 4: Resolve API key
Check in this order:
- Environment variable
$CORAL_API_KEY: !echo "${CORAL_API_KEY:-}"
- Credentials file: !
test -f ~/.coral/credentials.toml && cat ~/.coral/credentials.toml || echo "NO_CREDS"
If CORAL_API_KEY is set and non-empty, use it.
Otherwise, parse ~/.coral/credentials.toml and extract the api_key value from [default].
If no key found:
No API key found. Run /coral login to authenticate, or set the CORAL_API_KEY environment variable.
Stop.
Step 5: Resolve marketplace URL
Check in this order:
$CORAL_MARKETPLACE_URL environment variable
marketplace_url from ~/.coral/credentials.toml [default]
- Default:
https://marketplace.coralprotocol.ai
Step 6: Upload
curl -s -w "\nHTTP_STATUS:%{http_code}" \
-X POST "<marketplace_url>/api/v1/agents" \
-H "Authorization: Bearer <api_key>" \
-H "Content-Type: text/plain" \
--data-binary @coral-agent.toml
Step 7: Handle response
Parse the HTTP status code and response body from the curl output.
HTTP 200 — Success:
The response body is {"slug": "<slug>", "version": "<version>"}.
Tell the user:
Published successfully!
- Agent:
<slug>@<version>
- View:
<marketplace_url>/api/v1/agents/<slug>
Your agent is now discoverable on Coral Marketplace.
HTTP 400 — Validation or parse error:
Response: {"error": "validation_error" | "parse_error", "message": "..."}
Show the error message and provide specific fix guidance based on common errors:
- "Unsupported edition" → Set
edition = 3
- "Edition 3 requires [marketplace] section" → Add
[marketplace] section
- "Invalid slug" → Follow slug rules (1-32 chars, lowercase, no consecutive hyphens)
- "Invalid version" → Use semver (e.g.,
1.0.0)
- "[agent].name is required" → Add a name field
- "At least one runtime" → Add
[runtimes.executable] or [runtimes.docker]
HTTP 401 — Unauthorized:
Response: {"error": "unauthorized" | "api_key_expired", "message": "..."}
Authentication failed:
Run /coral login to re-authenticate.
HTTP 403 — Forbidden:
Response: {"error": "forbidden", "message": "..."}
Your API key does not have the publish scope.
Create a new API key with publish permissions at the marketplace.
HTTP 409 — Conflict:
Response: {"error": "conflict", "message": "..."}
Conflict:
This typically means either:
- The slug is owned by another publisher — choose a different slug
- This exact version already exists — bump the version number
HTTP 5xx — Server error:
Marketplace server error. Try again in a few minutes.
Check marketplace health: <marketplace_url>/health
Connection error:
Could not connect to <marketplace_url>.
Check your network connection and the marketplace URL.