Skip to main content

agentskills-http

PyPI Python 3.12 | 3.13 License: MIT

HTTP static-file skill provider for the Agent Skills SDK.

Serves Agent Skills from any static HTTP file host - S3, Azure Blob, CDN, GitHub Pages, Nginx, etc. Expects the same directory-tree layout as the filesystem provider, served over HTTP.

Installation

pip install agentskills-http

Requires Python 3.12 or newer. Installs agentskills-core, httpx, and pyyaml as dependencies.

Expected URL Layout

https://cdn.example.com/skills/
├── incident-response/
│   ├── SKILL.md
│   ├── references/severity-levels.md
│   ├── scripts/page-oncall.sh
│   └── assets/flowchart.mermaid
└── another-skill/
    └── SKILL.md

Usage

from agentskills_core import SkillRegistry
from agentskills_http import HTTPStaticFileSkillProvider

async with HTTPStaticFileSkillProvider("https://cdn.example.com/skills") as provider:
    registry = SkillRegistry()
    await registry.register("incident-response", provider)

    skill = registry.get_skill("incident-response")
    meta = await skill.get_metadata()
    body = await skill.get_body()

Custom Headers

Pass authentication or other headers:

from agentskills_http import HTTPStaticFileSkillProvider

provider = HTTPStaticFileSkillProvider(
    "https://cdn.example.com/skills",
    headers={"Authorization": "Bearer <token>"},
)

Bring Your Own Client

Supply a pre-configured httpx.AsyncClient for full control over timeouts, proxies, etc.:

import httpx
from agentskills_http import HTTPStaticFileSkillProvider

client = httpx.AsyncClient(timeout=30, headers={"Authorization": "Bearer <token>"})
provider = HTTPStaticFileSkillProvider("https://cdn.example.com/skills", client=client)
# caller is responsible for closing the client

Note: client and headers are mutually exclusive. Configure headers on the client directly when providing your own.

API

HTTPStaticFileSkillProvider(base_url, *, client=None, headers=None, params=None, require_tls=False, max_response_bytes=10_485_760, revalidate=False)

Parameter Type Default Description
base_url str - Root URL where the skill tree is hosted
client AsyncClient | None None Pre-configured httpx client (caller manages lifecycle)
headers dict | None None Extra headers sent with every request
params dict | None None Query parameters appended to every request
require_tls bool False Reject http:// URLs with ValueError
max_response_bytes int 10_485_760 Maximum allowed response size in bytes
revalidate bool False Re-check cached SKILL.md on every access with If-None-Match / If-Modified-Since
resource_manifest bool False Enable list_resources() by reading a per-skill index.json
timeout float 30.0 Request timeout in seconds (ignored when you supply client)
max_retries int 2 Retries after the initial attempt, for retryable failures only
retry_backoff float 0.5 Base delay in seconds for exponential backoff
max_retry_delay float 30.0 Ceiling on any single backoff sleep

Note: client and headers/params are mutually exclusive. Configure headers and params on the client directly when providing your own.

Method Returns Description
get_metadata(skill_id) dict[str, Any] Parsed YAML frontmatter from SKILL.md
get_body(skill_id) str Markdown body after the frontmatter
get_script(skill_id, name) bytes Raw script content
get_asset(skill_id, name) bytes Raw asset content
get_reference(skill_id, name) bytes Raw reference content
list_resources(skill_id) dict[str, list[str]] Resource names from index.json (requires resource_manifest=True)
invalidate(skill_id=None) None Drop cached SKILL.md content for one skill, or all skills
aclose() None Close the HTTP client (if owned by the provider)

Supports async with for automatic cleanup.

Resource Discovery

A static file host cannot be enumerated: there is no portable directory listing over plain HTTP. By default this provider therefore reports that it cannot list resources — list_resources() raises ResourceListingNotSupportedError — rather than returning an empty mapping that would look like a skill with no resources.

If you control the host, publish a small manifest at {base_url}/{skill_id}/index.json:

{
  "references": ["severity-levels.md"],
  "scripts": ["page-oncall.sh"],
  "assets": ["flowchart.mermaid"]
}

Then opt in:

provider = HTTPStaticFileSkillProvider(BASE, resource_manifest=True)
listing = await provider.list_resources("incident-response")

Missing categories default to empty lists. A manifest is host-supplied data whose entries are later interpolated into URLs, so names failing the identifier-safety check are dropped. If a given skill has no index.json, list_resources() raises ResourceListingNotSupportedError for that skill — again, not an empty result.

Caching

SKILL.md responses are cached per provider instance. Without it a single skill costs up to five round-trips per agent session — twice during registration, once per catalog build, and again on each tool call. Scripts, assets and references are not cached.

By default the cache is served until you call invalidate(). If your host serves mutable skills and the process is long-lived, opt into conditional revalidation instead:

provider = HTTPStaticFileSkillProvider(BASE, revalidate=True)

That sends If-None-Match / If-Modified-Since on every access and reuses the cached body on 304. It costs one cheap round-trip per access, so prefer the default plus an explicit invalidate() when you control publishing.

Error Handling

Scenario Exception Retried
404 / 410 on SKILL.md SkillNotFoundError No
404 / 410 on a resource ResourceNotFoundError No
5xx, 408, 425, 429 SkillUnavailableError Yes
Timeouts, connection and protocol errors SkillUnavailableError Yes
401 / 403 AgentSkillsError No
Other 4xx, oversized responses AgentSkillsError No

All exceptions inherit from AgentSkillsError.

The split between SkillNotFoundError and SkillUnavailableError is the point of the taxonomy: a 503 means the skill may well exist and the same request could succeed in a moment, whereas a 404 means it is gone. Collapsing both into "not found" turns a retryable blip into a permanent-looking failure, and nothing downstream can tell the difference.

Retries

Retryable failures are retried with exponential backoff and full jitter:

provider = HTTPStaticFileSkillProvider(
    BASE,
    max_retries=2,          # attempts after the first; 0 disables
    retry_backoff=0.5,      # base delay in seconds
    max_retry_delay=30.0,   # ceiling on any single sleep
)

Jitter matters because a registry builds its catalog concurrently — without it, every skill fetch would retry in lockstep and hit the recovering server as one wave.

Retry-After is honoured in both the delay-seconds and HTTP-date forms. If the server asks for longer than max_retry_delay, the request is not retried: blocking a request path for minutes is worse than failing fast. The advised delay is still available to the caller as SkillUnavailableError.retry_after, so a scheduler can act on it.

Security

  • Input validation - Skill IDs and resource names are validated against a safe-character pattern (^[a-zA-Z0-9][a-zA-Z0-9._-]*$) to prevent path-traversal and injection attacks.
  • TLS warnings - A UserWarning is emitted when base_url uses unencrypted HTTP. Set require_tls=True to reject HTTP URLs entirely.
  • Redirect protection - The internally-created HTTP client does not follow redirects by default, preventing open-redirect SSRF.
  • Timeouts - Default 30-second timeout on all HTTP requests. Configure via timeout.
  • Response size limits - Responses exceeding 10 MB (default) are rejected before processing. Configure via max_response_bytes.
  • Error-message sanitization - Messages carry the status code and the path relative to base_url — never the host, never a query string. The underlying httpx exception is deliberately not chained (from None), because httpx.HTTPStatusError renders the full request URL including its query string, which is exactly where SAS tokens and signed-URL signatures live. Chaining it leaked credentials into every traceback.

For the full security policy, see SECURITY.md.

Deployment Considerations

  • Rate limiting - The SDK does not enforce rate limits on MCP tool calls or HTTP requests. Deploy behind a reverse proxy or API gateway that provides rate limiting in production environments.
  • Credential management - Do not store secrets (API keys, SAS tokens, Authorization headers) in config files committed to version control. Use environment variables or a secret manager instead.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

agentskills_http-0.3.0.tar.gz (14.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

agentskills_http-0.3.0-py3-none-any.whl (13.2 kB view details)

Uploaded Python 3

File details

Details for the file agentskills_http-0.3.0.tar.gz.

File metadata

  • Download URL: agentskills_http-0.3.0.tar.gz
  • Upload date:
  • Size: 14.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for agentskills_http-0.3.0.tar.gz
Algorithm Hash digest
SHA256 0460e608d0357c8031c312747f0122ad3ddf082660cae5dbf069a7dbf1d3888c
MD5 9b3363ce6442e289f03b7e7da188348b
BLAKE2b-256 503e21cf4b4d9dbf73c463ee6b2cbbeb8275e3397b99ebca2634c0fe3a474f65

See more details on using hashes here.

Provenance

The following attestation bundles were made for agentskills_http-0.3.0.tar.gz:

Publisher: publish.yml on pratikxpanda/agentskills-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file agentskills_http-0.3.0-py3-none-any.whl.

File metadata

File hashes

Hashes for agentskills_http-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 136355850ed9c57e055e564d787122acd0fc77a29681fc1b0f6eee19642c6735
MD5 5a8f8d7cdb2e5c558e253a2af2ed332a
BLAKE2b-256 63f1dddf137848c85c2ae253d37221cd09108d4769b4c83313332ee570fd065f

See more details on using hashes here.

Provenance

The following attestation bundles were made for agentskills_http-0.3.0-py3-none-any.whl:

Publisher: publish.yml on pratikxpanda/agentskills-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page