Skip to main content

Publishing Guide

Applies to SDK 0.16+ · Last updated: 2026-06-12

Publishing a pack to AgentNode makes your AI tool discoverable, installable, and verifiable by any agent developer. This guide walks through the full process from account creation to published pack.

Step 1: Create your publisher account

Sign up at agentnode.net/auth/register and enable two-factor authentication. Your publisher namespace (e.g., your-org) appears in every package you publish and cannot be changed later.

Step 2: Structure your project

A minimal pack has three files: the manifest, a pyproject.toml for Python packaging, and the tool module with your tool functions.

project structure
my-pack/
  agentnode.yaml          # ANP manifest (required)
  pyproject.toml          # Python package config (required)
  src/
    my_pack/
      __init__.py
      tool.py             # Tool functions (required)

Step 3: Write your agentnode.yaml manifest

The manifest is the source of truth for what your pack does, what it needs, and how it integrates. See the ANP Manifest Reference below for every field.

agentnode.yamlyaml
manifest_version: "0.2"
package_id: "github-integration-pack"
package_type: "toolpack"
name: "GitHub Integration Pack"
publisher: "your-namespace"
version: "1.0.0"
summary: "Interact with GitHub repos, issues, and PRs."
description: "A comprehensive toolkit for GitHub automation including issue creation, PR review, repository management, and webhook handling."

runtime: "python"
entrypoint: "github_integration_pack.tool"
install_mode: "package"
hosting_type: "agentnode_hosted"

capabilities:
  tools:
    - name: "create_issue"
      capability_id: "github_integration"
      description: "Create a new GitHub issue"
      entrypoint: "github_integration_pack.tool:create_issue"
      input_schema:
        type: "object"
        properties:
          token:
            type: "string"
            description: "GitHub personal access token"
          repo:
            type: "string"
            description: "Repository in owner/repo format"
          title:
            type: "string"
          body:
            type: "string"
        required: ["token", "repo", "title"]
    - name: "list_repos"
      capability_id: "github_integration"
      description: "List repositories for authenticated user"
      entrypoint: "github_integration_pack.tool:list_repos"
      input_schema:
        type: "object"
        properties:
          token:
            type: "string"
        required: ["token"]

permissions:
  network:
    level: "unrestricted"
    justification: "Requires access to GitHub API"
  filesystem:
    level: "none"
  code_execution:
    level: "none"
  data_access:
    level: "input_only"

compatibility:
  frameworks: ["generic"]
  python: ">=3.10"

tags: ["github", "integration", "devtools", "automation"]

Step 4: Implement your tool functions

src/github_integration_pack/tool.pypython
from agentnode_sdk.exceptions import AgentNodeToolError

def create_issue(inputs: dict) -> dict:
    """Create a new GitHub issue."""
    token = inputs["token"]
    repo = inputs["repo"]
    title = inputs["title"]
    body = inputs.get("body", "")

    # Your implementation here
    response = _github_api(token, f"/repos/{repo}/issues", {
        "title": title, "body": body
    })
    return {"issue_number": response["number"], "url": response["html_url"]}

def list_repos(inputs: dict) -> dict:
    """List repositories for authenticated user."""
    token = inputs["token"]
    repos = _github_api(token, "/user/repos")
    return {"repos": [{"name": r["name"], "url": r["html_url"]} for r in repos]}

# Optional: backward-compatible run() wrapper for v0.1 callers
# Not required for v0.2 — per-tool entrypoints (tool:create_issue, tool:list_repos) are used instead
def run(inputs: dict) -> dict:
    operation = inputs.get("operation", "list_repos")
    dispatch = {"create_issue": create_issue, "list_repos": list_repos}
    handler = dispatch.get(operation)
    if not handler:
        raise AgentNodeToolError(f"Unknown operation: {operation}", tool_name=operation)
    return handler(inputs)

Step 5: Validate and verify locally

Run the local verification pipeline to confirm your package will reach Gold tier on first publish. This simulates the exact same checks the server runs.

terminal
$ agentnode validate .

Validating github-integration-pack@1.0.0
  [PASS] Manifest syntax valid
  [PASS] Required fields present
  [PASS] Verification cases defined (2 cases)
  [PASS] Cassette files exist

  Max tier              Gold
  Mode                  fixture
  Cases                 2

For API connectors that make external HTTP calls, record VCR cassettes first:

terminal
$ agentnode record-cases .

Recording cassettes for github-integration-pack
  [OK] create_issue -> fixtures/cassettes/create_issue.yaml
  [OK] list_repos -> fixtures/cassettes/list_repos.yaml

  Cassette Warnings
  [DYNAMIC] Fields that may change between runs:
    - interactions[0].response.headers.Date

  Next: agentnode verify-local .

Then run the full verification pipeline locally:

terminal
$ agentnode verify-local .

Verifying github-integration-pack@1.0.0

  Pipeline
  [PASS] Install
  [PASS] Import
  [PASS] Smoke
  [PASS] Tests      2 passed in 0.3s
  [PASS] Contract
  [PASS] Reliability  100.0%
  [PASS] Determinism  100.0%

  Score                 95/95
  Tier                  Gold
  Mode                  fixture

  This package will reach Gold tier after publishing.

Step 6: Publish

Set your API key (from your dashboard), then publish:

terminal
$ export AGENTNODE_API_KEY=ank_your_key_here
$ agentnode publish .

  AgentNode Publish
  Package    github-integration-pack@1.0.0
  Type       toolpack

  Validation    8 checks passed
  Artifact      14.2 KB, 6 files

  Publishing to api.agentnode.net...
  Published github-integration-pack@1.0.0

  https://agentnode.net/packages/github-integration-pack

Use --dry-run to preview without uploading, --skip-validate to continue past validation warnings, or --token <key> to pass the API key directly.

Tip: Packages that pass agentnode verify-local reach Gold tier on their first publish attempt. No debugging in the blind. The recommended flow is: initvalidaterecord-casesverify-local → publish.