Most “ship an AI agent” tutorials start in a monorepo the size of a small city.
I wanted the opposite: an empty directory, one command, and a provider that already knew how to sign its answers.
That tool now exists on PyPI as create-aimarket-agent 0.1.0 — a standalone scaffolder for AIMarket Protocol v2 capability providers. Docs in five languages. Generator CI claims 47 tests and 100% branch coverage. MIT.
It does not publish you to a marketplace. That part stays manual on purpose.
One command. Stable names.
uvx create-aimarket-agent my-agent --kind tool --metis
cd my-agent
uv sync --extra dev
uv run python configure_provider.py
uv run pytest
uv run python validate_manifest.py
uv run python agent.py
The CLI, flags, filenames, and API fields stay English everywhere. Localization covers the docs, not the contract.
Kinds:
create-aimarket-agent my-tool --kind tool
create-aimarket-agent my-data --kind data-provider
create-aimarket-agent my-orchestrator --kind orchestrator
create-aimarket-agent my-agent --no-metis
Scaffolding is atomic: stage in a temp folder, rename into place, clean up. A failed copy leaves no half-written repo.
Project names are allow-listed before they touch source or JSON. That sounds boring until the first time a fancy name breaks a Dockerfile.
What lands on disk
| Path | Job |
|---|---|
agent.py |
FastAPI /health + /invoke
|
capability.json |
Protocol v2 manifest |
provider_signing.py |
Persistent Ed25519 identity + request-bound signatures |
configure_provider.py |
Writes provider_pubkey into the manifest |
validate_manifest.py |
Fail-closed checks before you even think about publish |
test_agent.py |
API, signature, request-size tests |
Dockerfile |
Non-root image, key volume at /data
|
.github/workflows/test.yml |
CI for the generated project |
The default manifest looks like this (placeholders replaced with your slug):
{
"product_id": "my-agent",
"capability_id": "my-agent.invoke@v1",
"name": "my-agent",
"description": "A generated AIMarket tool capability",
"invoke_url": "http://127.0.0.1:8080/invoke",
"publisher_id": "community",
"provider_pubkey": "",
"price_per_call_usd": 0.001,
"input_schema": {"type": "object", "additionalProperties": true},
"output_schema": {"type": "object", "additionalProperties": true},
"verification": {"metis": true}
}
configure_provider.py fills provider_pubkey. validate_manifest.py rejects duplicate JSON keys, broken Ed25519 keys, non-finite prices, bad URLs, and public HTTP endpoints before you ship.
The skeleton /invoke only accepts the product and capability ids declared in its own manifest. An untrusted caller cannot make your key sign someone else’s identity.
The part I actually cared about: the stamp
Pretty agents are easy. Replay-resistant receipts are not.
The generated signer keeps a 32-byte Ed25519 seed at mode 0600. Symlinks and non-regular files get rejected. Responses sign a canonical envelope with:
capability_idproduct_id- SHA-256 of the input
- the result
That binding is the point. Steal a response for request A and it should not verify as a reply to request B.
The signature is a receipt for what this provider returned. It is not an authorization gate for random internet callers. Keep 8080 on loopback until real HTTPS ingress, concurrency, and rate limits sit in front.
Docker without drama
docker build -t my-agent .
docker run --read-only --tmpfs /tmp \
-p 127.0.0.1:8080:8080 \
-v my-agent-key:/data my-agent
Runs as UID 65532, health-checks /health, stores the key under /data/provider.key.
Back up that key before you register anything. Rotate it and the Hub’s stored provider_pubkey becomes a stranger.
From skeleton to something useful: THEMIS
The README does not stop at “echo hello.” There is a full tutorial that turns the scaffold into THEMIS — a procurement gate that answers:
Should this candidate agent be approved, sent to human review, or rejected?
Deterministic policy checks. Projected cost. OWASP Agentic risk mappings. Optional lazy Metis verification that never silently overrides the verdict. Same request-bound signing model.
- Tutorial: docs/tutorials/themis.en.md
- Finished repo: alexar76/themis
If you only want a tool capability, ignore THEMIS. If you want a real admission gate, start there.
What this is not
- Not auto-publish. Stake, publisher identity, trust policy, and Hub registration stay explicit operator steps.
- Not “the monorepo.” The GitHub repo is a read-only mirror of the AI-Factory tree. PRs there get overwritten on the next sync — open an issue instead.
- Not a substitute for HTTPS. Loopback + signature ≠ production exposure.
Try it
uvx create-aimarket-agent my-agent --kind tool --metis
- Docs: alexar76.github.io/create-aimarket-agent
- Source / issues: github.com/alexar76/create-aimarket-agent
- Package:
create-aimarket-agenton PyPI (0.1.0as of this writing)
Empty folder in. Signed provider out. Marketplace listing still your call — which is exactly how I wanted it.






Top comments (0)