> For the complete documentation index, see [llms.txt](https://docs.concurrence.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.concurrence.com/developer-guide/platform-api/workspaces/skills.md).

# Skills

Configure LLM-backed micro-agent capabilities with system prompts, schemas, and tool access.

Skills are companion agent capabilities. They are LLM-backed micro-agents that execute specific tasks within a conversation. Unlike Classic API tools (which run versioned code packages), skills are configured declaratively with a system prompt, input/output schema, and model selection.

{% hint style="info" %}
**Different from Classic API Tools.** Classic API [Tools](/developer-guide/classic-api/core-api/tools.md) are versioned code packages from Git repos. Platform API Skills are LLM-backed declarative micro-agents with prompt-based configuration. Choose Tools for custom code execution, Skills for LLM-native reasoning.
{% endhint %}

## API Surface

### Create a Skill

{% openapi src="<https://platform.api-us.concurrence.com/v1/openapi.json>" path="/v1/{workspace\_id}/skills" method="post" %}
<https://platform.api-us.concurrence.com/v1/openapi.json>
{% endopenapi %}

### List Skills

{% openapi src="<https://platform.api-us.concurrence.com/v1/openapi.json>" path="/v1/{workspace\_id}/skills" method="get" %}
<https://platform.api-us.concurrence.com/v1/openapi.json>
{% endopenapi %}

### Get a Skill

{% openapi src="<https://platform.api-us.concurrence.com/v1/openapi.json>" path="/v1/{workspace\_id}/skills/{skill\_id}" method="get" %}
<https://platform.api-us.concurrence.com/v1/openapi.json>
{% endopenapi %}

### Update a Skill

{% openapi src="<https://platform.api-us.concurrence.com/v1/openapi.json>" path="/v1/{workspace\_id}/skills/{skill\_id}" method="put" %}
<https://platform.api-us.concurrence.com/v1/openapi.json>
{% endopenapi %}

### Delete a Skill

{% openapi src="<https://platform.api-us.concurrence.com/v1/openapi.json>" path="/v1/{workspace\_id}/skills/{skill\_id}" method="delete" %}
<https://platform.api-us.concurrence.com/v1/openapi.json>
{% endopenapi %}

### Get Skill References

{% openapi src="<https://platform.api-us.concurrence.com/v1/openapi.json>" path="/v1/{workspace\_id}/skills/{skill\_id}/references" method="get" %}
<https://platform.api-us.concurrence.com/v1/openapi.json>
{% endopenapi %}

### Test a Skill

{% openapi src="<https://platform.api-us.concurrence.com/v1/openapi.json>" path="/v1/{workspace\_id}/skills/{skill\_id}/test" method="post" %}
<https://platform.api-us.concurrence.com/v1/openapi.json>
{% endopenapi %}

The tester sends the same model request a conversation does, with the same thinking and structured-output settings. It calls the skill's real integration endpoints, under the same [retry and unknown-outcome rules](/developer-guide/platform-api/integrations.md#endpoint-retries), and answers each static tool with its entry in `static_tool_mocks`. `sub_tool_logs` records every tool call with its input, output, and whether it succeeded.

When a run fails, `error` says why in the platform's own words and `failure_class` names the cause:

* `model_rejected`: the model provider refused a request the run sent (HTTP 400, 413, or 422). Check the skill's tool definitions and schemas, its prompt size, and its model settings.
* `rounds_exhausted`: the run used its whole tool-round budget.
* `generic`: anything else, including a tool call the model wrote out as text instead of calling the tool.

`rounds` counts the rounds the run started, including one that failed.

## Input Schema Compatibility

A skill `input_schema` is used as an LLM tool schema during execution. Keep it in the supported tool-schema subset:

* The root schema must describe a single JSON object.
* Do not use a top-level `$ref`, `anyOf`, `oneOf`, or `allOf`.
* Array-typed properties must declare `items`.

Unsupported shapes are rejected on create/update with `422` because they can cause the LLM tool call to fail silently at runtime.

## Execution Configuration

Skills execute as multi-turn LLM agents. Configure their model, token and result limits, timeout, thinking, structured output, caching, approval requirement, and maximum tool-use turns through the request schema embedded above.

A skill `model` is `claude-sonnet-5-5`, `claude-opus-5-5`, or `claude-haiku-5-5`, and a skill created without one stores `claude-sonnet-5-5`. Create and update return `422` for a retired Claude id, with an error that names the current model of the same tier, such as `retired Claude model id; use claude-sonnet-5-5`. `claude-sonnet-5-5` replaces `claude-sonnet-5` and `claude-sonnet-4-6`, `claude-opus-5-5` replaces `claude-opus-4-8`, and `claude-haiku-5-5` replaces `claude-haiku-4-5`. Any other id the platform doesn't serve also returns `422`. Skill reads return the current id. The platform doesn't send sampling controls to these models, so `temperature` and `top_p` have no effect.

Left unset, `thinking_effort` gives each model the least thinking it allows: `claude-haiku-5-5` doesn't think, `claude-sonnet-5-5` thinks only between tool calls, and `claude-opus-5-5` thinks at low effort. Set `thinking_effort` to `low`, `medium`, or `high` when a skill needs deeper reasoning. Any thinking counts against `max_tokens`, so leave room for the answer. Conversations and the [skill tester](#test-a-skill) build the request the same way.

A `result_schema` must be valid JSON Schema, or create and update return `422`. With `use_structured_output: true`, the schema must also constrain `status` to an enum of `success` and `failure` and stay within the supported structured-output subset; otherwise the write returns `422` naming the failing requirement. An update checks only when it sends `result_schema` or `use_structured_output`. The [skill tester](#test-a-skill) builds the same structured request as conversations, so a structured skill returns JSON matching its `result_schema` there too.

A skill that calls an integration endpoint declared `varies` sets `write_kind` to `booking`, `cancellation`, `reschedule`, `message`, or `other` to say what its write does. A sub-tool endpoint that declares its own kind writes that kind, whatever the skill says. See [Endpoint Write Declarations](/developer-guide/platform-api/integrations.md#endpoint-write-declarations).

With `approval_required: true`, each call to the skill waits for an operator's approve or reject decision, as an approval-gated endpoint does, and an approved call runs as it would without approval. Only text conversations offer such a skill; see [Approval-Gated Integration Writes](/developer-guide/platform-api/integrations/approval-gated-integration-writes.md#key-concepts) for where it isn't offered.

Tool names must be unique within a skill, counting static tools and integration tools together. An integration tool is named `<integration>_<endpoint>`. Create and update return `422` with a message that lists each repeated name. An update checks only when it sends `integration_tools` or `static_tools`, so a stored skill with a repeated name can still be renamed or disabled.

A skill whose last round stops at the token limit or on a model refusal without producing text returns a failed result rather than an empty successful one.

The schema accepts and returns `enable_citations` and `checkpoint_enabled`, but the runtime does not read either field. Setting them has no effect on execution.

## Integration with External APIs

Skills can call external APIs through [Integrations](/developer-guide/platform-api/integrations.md) and inline static tool definitions. Integration tool references identify the integration and endpoint by name.

### Bind Skill Inputs to Integration Tools

A Context Graph state can fill a skill’s input using `context_bindings` or `context_binding_aliases`; see [Pass Context to Tool Parameters](/developer-guide/guides/conversation-context.md). On voice calls, a skill input bound to a declared context key that the call did not start with is refused; see [Set Context on a Live Voice Call](/developer-guide/guides/live-call-context.md#how-the-agent-uses-the-value). The skill’s integration tool reference can then map its inputs into endpoint parameters:

```json
{
  "integration": "test-directory",
  "endpoint": "lookup",
  "skill_input_bindings": {
    "region_header": "region"
  }
}
```

This is an `integration_tools` entry, not a complete skill request. Both the target endpoint parameter and source skill input must be declared in their respective input schemas. Create/update rejects references to undeclared fields. The runtime hides the target from the companion model and injects the parent skill input when the sub-tool executes. Missing source input prevents that sub-tool call; a model argument cannot substitute for it. The standalone skill tester also applies this mapping, but its parent input must be supplied by the test request.

An integration endpoint can route that parameter into an HTTP header with an exact binding such as `"X-Region": "$param.region_header"` in its `headers` configuration. The value must be a non-null scalar without line breaks. Missing or invalid values fail before an outbound request. A consumed header parameter is excluded from the ordinary query/body parameters. Static header values remain supported; this is an exact binding, not arbitrary string interpolation.

Use verified identity bindings for identity-derived authentication. Caller-supplied skill or conversation input is not an access-control credential, and header routing does not make that input trusted.

## References

Before modifying or deleting a skill, check what depends on it:

The references operation returns context graphs (with specific states) and services that reference the skill's slug. This prevents breaking live conversation flows by accidentally removing a skill that is in use.

## Testing

Use the [tool testing](/developer-guide/platform-api/functions/tool-testing.md) endpoints to execute a skill in isolation without starting a conversation. Useful for validating prompt engineering and schema design before wiring into a context graph.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.concurrence.com/developer-guide/platform-api/workspaces/skills.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
