Agently Docs

Agently documentation for building AI applications with stable outputs, observable actions, and durable workflows.

View the Project on GitHub AgentEra/Agently

Skills Executor

Languages: English · 中文

Agently Skills follow the standard Skills layout: SKILL.md is the capability definition, with optional scripts/, references/, and assets/ resources. Agently does not define a separate Skill authoring manifest.

---
name: release-review
description: Use when checking release readiness and rollback risk.
---

# Release Review

Follow this checklist before recommending a release or rollback...

Declare And Install

For normal Agent runtime, declare Skills on the Agent with use_skills(...). The Skills Executor treats repository/package selectors like Action candidates: it records the source first, performs lightweight SKILL.md discovery during planning, and installs the full Skill only when the planner selects or requires it.

agent.use_skills(
    [{"source": "anthropics/skills", "subpath": "skills/docx"}],
    mode="required",
)

Use install_skills_pack(...) for advanced pool management: prewarming, offline mirrors, deterministic CI fixtures, or explicit registry maintenance. install_skills(...) remains the authoring/smoke-test path for one local Skill directory.

When you author a local Skill, keep it in a real standalone directory that matches the standard layout. Do not build inline SKILL.md strings inside business code and do not use root-level YAML manifests such as skill.yaml. The application should pass the directory path to the executor:

my-skill/
|-- SKILL.md
|-- scripts/
|-- references/
`-- assets/
report = Agently.skills_executor.install_skills_pack(
    "anthropics/skills",
    fetch=True,
    subpath="skills/docx",
    trust_level="remote",
)

Remote installs clone the repository into Agently’s local registry source cache, copy standard SKILL.md packages into the registry, and record source URL, ref, resolved commit, subpath, trust level, and checksums. Installing a remote Skill never executes bundled scripts.

install_skills(...) copies a standard local Skill directory into the local registry. The installed Skill root still contains SKILL.md directly. Agently adds its own management files under .agently/ inside the installed copy.

.agently/skills/release-review/
|-- SKILL.md
|-- scripts/
|-- references/
|-- assets/
`-- .agently/
    |-- install.json
    |-- decision_card.json
    |-- resource_index.json
    `-- checksums.json

The .agently/ files speed up routing and inspection. They are not Skill capability definitions. If a derived file is missing or stale, Agently rebuilds or falls back to reading SKILL.md.

skill_id is derived from the SKILL.md frontmatter name: lowercase, whitespace becomes -, and only a-z0-9._- remains. Use the returned contract["skill_id"] when wiring later calls.

contract = Agently.skills_executor.install_skills("./release-review")
agent.use_skills([contract["skill_id"]], mode="model_decision")

Root-level non-standard manifests such as skill.yaml, skill.json, or agently.skill.yaml are rejected. Files with those names inside scripts/, references/, or assets/ are treated as ordinary resources.

Select

Use use_skills(...) to expose installed or remote Skills as route candidates. The model sees concise decision cards first; full guidance and resources are materialized only when the Skills route executes.

agent = Agently.create_agent("ops-assistant")
agent.use_skills(["release-review"], mode="model_decision")
agent.use_skills([{"source": "anthropics/skills", "subpath": "skills/docx"}], mode="required")

Use resolve_skills_plan(...) when you need to inspect which Skills would be used. Required Skills keep the caller-provided order. Multiple optional candidates are ordered by the model.

plan = await agent.async_resolve_skills_plan(
    "Should this release be blocked?",
    skills=["release-review", "incident-triage"],
    mode="model_decision",
)

Execute

Use run_skills_task(...) when the task must be answered through selected Skills. By default, execution is single_shot: Agently injects the selected SKILL.md guidance, decision cards, resource summaries, and the task into one model request. Skills that declare execution: staged or allowed-tools can run through the TriggerFlow-backed staged and react strategies. When actions are available, react delegates tool/action planning and execution to the Agent ActionRuntime, so kwargs schemas, MCP tools, policy, approvals, concurrency, and execution-environment handling stay on the Action layer instead of being reimplemented by Skills.

execution = await agent.async_run_skills_task(
    "Review this release and give a go/no-go recommendation.",
    skills=["release-review"],
    mode="required",
)

print(execution.status)
print(execution.output)
print(execution.skill_logs)

output= uses the same schema grammar as .output(...); it is the structured-output contract for the Skill run. It describes the business result shape the Skill execution must produce, while output_format= controls whether that result is carried as JSON, flat Markdown, hybrid output, or automatic format selection. The older semantic_outputs= argument is kept only as a deprecated compatibility alias for Skills execution.

execution = await agent.async_run_skills_task(
    "Write a release decision.",
    skills=["release-review"],
    mode="required",
    output={"decision": (str, "go or no-go", True)},
)

Agent prompt methods are also supported for explicit Skills execution. The Skill run consumes the current prompt snapshot, uses rendered prompt text as the task, and maps the output / output_format slots to output / output_format:

execution = await (
    agent
    .info({"release": "4.1.2.x"})
    .input("Write a release decision.")
    .output({"decision": (str, "go or no-go", True)}, format="json")
    .async_run_skills_task(skills=["release-review"], mode="required")
)

set_agent_prompt(...) values are inherited and kept for later turns. set_request_prompt(...) / quick prompt values are frozen into the Skill run and then cleared from the pending request. Explicit output= and output_format= arguments override prompt-derived defaults.

output_format= selects how that model response is controlled. Leave it as "auto" for ordinary Skill answers. Auto is structural: it chooses "flat_markdown" for flat string-only schemas, "hybrid" for top-level dicts that combine string fields with complex list/object fields, and "json" for boolean/numeric control fields, all-complex schemas, and non-dict outputs. Use explicit "json" for compact machine-readable results, judges, booleans, numbers, or downstream JSON-only contracts.

execution = await agent.async_run_skills_task(
    "Draft a release announcement as HTML.",
    skills=["release-review"],
    mode="required",
    output={"html": (str, "render-ready HTML", True)},
    output_format="flat_markdown",
)

For fixed required fields, prefer the third tuple element in the schema:

output = {
    "rules": [
        {
            "rule_id": (str, "Stable rule id", True),
            "passed": (bool, "Whether this rule passed", True),
            "evidence": (str, "Concise evidence; empty string is allowed", False),
        }
    ],
    "passes": (bool, "Overall pass/fail", True),
}

Use runtime ensure_keys= only for paths that are conditional or decided at runtime. max_retries=3 means Agently can make up to three additional model attempts when parsing, required keys, strict output validation, or custom validators fail. Retries often recover ordinary omissions, markdown header mistakes, and auto-format degradation to JSON. They can still fail after all attempts when a model repeatedly echoes placeholder scaffolding, returns prose for boolean or numeric fields, produces malformed nested arrays, truncates a large prompt, or must fill many wildcard paths such as rule_results[*].evidence. For model judges with many rules, prefer output_format="json", keep the schema shallow when possible, and split very large rule sets into smaller judge calls.

Direct Skills execution streams runtime items through stream_handler:

effort="fast" uses the low-overhead single-shot path. effort="normal" runs the full preflight -> research -> plan -> execute -> verify -> reflect -> finalize chain. effort="max" uses the same chain with a larger retry budget and is the planned hook for Dynamic Task escalation.

Use agent.set_settings("effort_presets", {...}) when you need to override the built-in profile mapping to strategy, model key, step budget, retry count, or artifact inline limit:

agent.set_settings("effort_presets", {
    "fast": {"strategy": "single_shot", "reason_key": "reason_fast", "step_budget": 1},
    "normal": {"strategy": "runtime_chain", "reason_key": "reason", "retry_count": 1},
})

execution = await agent.async_run_skills_task(
    "Draft a release decision.",
    skills=["release-review"],
    mode="required",
    effort="normal",
)

For a fully custom action strategy, register an effort strategy handler on the Skills Executor and invoke it through effort=. The handler receives the Agent runtime context, selected Skills plan, resolved effort config, and output format; it may request models, call Actions/MCP through the context, emit runtime stream items, and return the final output.

The handler follows the SkillsEffortStrategyHandler protocol:

def handler(
    *,
    context: SkillsExecutionContext,
    task: str,
    plan: SkillExecutionPlan,
    output_format: str | None = None,
    effort: str | None = None,
    effort_config: dict | None = None,
) -> Awaitable[Any] | Any: ...

The builtin handlers are registered through the same strategy table: single_shot, runtime_chain, staged, and react. Use Agently.skills_executor.list_effort_strategies() to inspect the available strategy names. A custom handler may replace a builtin only with replace=True; otherwise duplicate names fail closed. Builtin reference implementations live under agently/builtins/plugins/SkillsExecutor/AgentlySkillsExecutor/modules/effort_strategies/.

async def audit_plus_strategy(*, context, task, plan, effort_config, **_):
    await context.async_emit_runtime_stream({
        "type": "skills.audit_plus.checkpoint",
        "action": "checkpoint",
    })
    return await context.async_request_model(
        prompt={
            "task": task,
            "selected_skills": plan["selected_skills"],
            "policy": effort_config,
        },
        model_key="verifier",
        output_schema={"decision": (str, "go / no-go", True)},
        output_format="json",
    )

Agently.skills_executor.register_effort_strategy(
    "audit_plus",
    audit_plus_strategy,
)

agent.set_settings("effort_presets", {
    "audit_plus": {"strategy": "audit_plus", "custom_budget": 7},
})

execution = await agent.async_run_skills_task(
    "Audit this release.",
    skills=["release-review"],
    mode="required",
    effort="audit_plus",
)

Skills runtime model calls use symbolic stage keys: planner, research, reason, executor, verifier, reflector, and finalizer. If a key is not mapped in model_pool, Agently leaves the request on the agent’s inherited model instead of sending the symbolic key as a provider model name.

When Skills are selected through Agent auto-orchestration, model field stream items are bridged to stable paths like skills.model.fields.<field_path>.

Bundled scripts and resources are never executed just because a Skill is installed. When a selected Skill declares mcp, mcpServers, allowed-tools: [Bash], or allow-scripts, the Skills Executor mounts the required runtime actions on the current Agent before execution: MCP declarations route through agent.use_mcp(...), and Bash/script declarations route through a managed enable_shell(...) action scoped to the installed Skill directory. Local command and script capabilities are high-risk and require auto_allow=True or an approval handler; remote HTTP MCP can mount without that local-command approval.

If a selected Skill declares a missing capability and no existing Action/MCP tool matches it, the executor takes one conservative fallback step. Names that look like pure in-memory computation, parsing, validation, transformation, or format conversion can be synthesized as ephemeral Python sandbox actions. Business-system, network, file, messaging, payment, database, browser, or otherwise external capabilities are never synthesized; they fail closed with capability_missing until the host provides a real Action, MCP server, or connector package.

Acceptance Example

examples/agent_auto_orchestration/19_remote_skills_weather_event_ops.py exercises the 4.1.3 remote-connector path end to end: public remote Skills are declared with agent.use_skills(...), a free weather MCP server is registered through ActionRuntime, the model generates MCP action calls for real weather observations, and Skills Executor lazily materializes the selected Skills before running effort="normal".

Settings

Skill applicability comes from SKILL.md; Agently’s .agently/ files are descriptive install metadata only. Multi-step Skills execution composes Agently’s existing TriggerFlow, Action, and ExecutionEnvironment boundaries; human approval or durable wait/resume flows should be modeled through TriggerFlow pause_for(...) / continue_with(...) or Action / ExecutionEnvironment approval policies, not by mutating a closed SkillExecution snapshot.

Framework-level skills.* settings may still tune host behavior, such as whether optional Skill candidates disclose full guidance in ordinary prompts. Plugin defaults load first when present; framework settings are the final application-level defaults. Neither setting layer can replace SKILL.md as the Skill capability definition.

Use the public Skills Executor configuration helper for local registry options:

Agently.skills_executor.configure(
    registry_root="./.agently/skills-dev",
    allowed_trust_levels=["local"],
)

API Summary

SkillContract describes the installed standard Skill, Agently install metadata, decision card, resource index, and checksums. It does not contain framework-authored stage declarations.