Skip to main content

Reuse your AI stuff across the agent stack: COMPLETE skills into agent definitions and REALIZE them into running agents (glue over skill, aw, py2mcp).

Project description

coact

Reuse your "AI stuff" across the layers of the modern agent stack. coact ("co-act" — skills and agents acting as one reusable substrate) turns the skills you already have into agent definitions, and turns those definitions into agents that actually run.

python functions/scripts  →  .claude/skills/  →  .claude/agents/  →  running agents
        (py2mcp, aw)            (skill pkg)        COMPLETE (coact)    REALIZE (coact)

coact owns the two transitions the rest of the ecosystem doesn't:

  • COMPLETE — start from a .claude/skills/ skill and complete it into a .claude/agents/ definition: add the agent-only extras (persona, return contract, tool allowlist, model, memory) that a skill doesn't carry.
  • REALIZE — take a completed definition and produce something that runs, choosing the right backend (the host agent, the Claude Agent SDK, or MCP-exposed tools for a foreign host).

It is glue, not a new framework: it builds on skill (skill data model + registries), aw (the AgenticStep runtime), and py2mcp (Python → MCP). See misc/docs/REUSE.md.

Install

pip install coact            # core: COMPLETE + host realize + analysis (no LLM needed)
pip install coact[sdk]       # + the Claude Agent SDK realize backend (and aw)
pip install coact[mcp]       # + the py2mcp/FastMCP realize backend
pip install coact[litellm]   # + the provider-agnostic LiteLLM realize backend

Quick start

from coact import complete, emit_agent, realize

# 1. Complete a skill into an agent definition (mechanical — no LLM).
agent = complete(".claude/skills/ux-analyst")

# 2. See it: a valid .claude/agents/ markdown file.
print(emit_agent(agent, "claude-agents-md"))

# 3. Realize it the cheap way: materialize files so Claude Code runs it.
realize(agent, backend="host")

Prefer to look before you leap? Everything has a dry-run:

from coact import plan_completion

plan = plan_completion(".claude/skills/ux-analyst")
print(plan.render())   # every synthesized field + WHERE it came from + warnings

That extends to the one backend that touches disk: realize(agent, backend="host", dry_run=True) returns the agent files and skill links it would write — without creating any of them.

A complete, runnable walk through all of this — a real skill → completeemitrealize(host)realize(sdk)estimate/inventory — lives in examples/ (no LLM, no API key needed):

python examples/walkthrough.py

CLI

coact plan      .claude/skills/ux-analyst                 # dry-run with provenance
coact complete  .claude/skills/ux-analyst --dest .claude/agents
coact emit      .claude/skills/ux-analyst --target sdk-agent-dict   # a non-default emit target
coact realize   .claude/skills/ux-analyst --backend host
coact realize   .claude/skills/ux-analyst --backend host --dry-run   # preview; writes nothing
coact diff      .claude/skills/ux-analyst .claude/agents/ux-analyst.md
coact estimate  .claude/agents/a.md .claude/agents/b.md   # the cost gate
coact inventory .                                         # skills + agents + MCP tools
coact back      .claude/agents/ux-analyst.md              # lossy agent → skill stub
coact scaffold  .claude/agents/a.md .claude/agents/b.md   # a starter fleet shim (you own it)

The model in one minute

A SKILL.md is procedural knowledge injected into the caller's turn; a subagent is a separate worker with its own context, persona, tools, model, and a defined return value. They overlap heavily — an agent is mostly a skill plus a thin "extras" envelope. COMPLETE synthesizes that envelope; the two extras that actually matter are:

  1. the persona (system prompt / identity), and
  2. the return contract (a schema so a manager can consume the agent's output).

coact keeps the skill on disk as the single source of truth and makes the agent reference it by name — it never copies a skill body into an agent. One AgentDefinition object serializes to both the filesystem .claude/agents/*.md and the Agent SDK form.

The coact: frontmatter (optional)

To make the lift reproducible, a skill may carry an additive coact: block (ignored by every other tool). When present it wins over policy; when absent coact infers + reports what it guessed.

---
name: ux-analyst
description: Analyze a captured UX evidence bundle for usability issues.
coact:
  tools: [Read, Grep, Glob]
  model: sonnet
  memory: project
  returns:
    schema_ref: ov.schemas:UxFindings
  mcp:
    - module: ov.analyzers
      functions: [score_contrast, find_tap_targets]
---

Realization backends

backend what "running" means cost
host (default) materialize .claude/agents/*.md + link skills; the host agent (Claude Code) executes cheapest — no fan-out
sdk a RunnableAgent backed by the Claude Agent SDK that satisfies aw.AgenticStep (execute(input, context) -> (artifact, info)), so it drops into aw workflows in-process
mcp expose a skill's declared Python tools as a FastMCP server (via py2mcp) for any MCP client tool server
litellm a RunnableLLMAgent (also aw.AgenticStep) backed by LiteLLM — realize the same definition against any provider (OpenAI, Gemini, Mistral, Ollama, …); proof the definition isn't Anthropic-specific in-process
agent_step = realize(agent, backend="sdk")          # aw-compatible runnable
artifact, info = agent_step.execute(task, context={})

server = realize(".claude/skills/ux-analyst", backend="mcp")   # FastMCP handle

# same definition, a different provider — map model selectors however you like
llm_step = realize(agent, backend="litellm", model_map={"sonnet": "openai/gpt-4o"})
artifact, info = llm_step.execute(task)             # info["backend"] == "litellm"

Two boundaries to know

  • Topology is out of scope. A subagent definition can't express graphs, conditional edges, or cycles, and subagents can't spawn subagents. coact emits definitions + tool/MCP wiring and stops. Multi-agent orchestration is left to the host's manager or a thin shim you own (against the Agent SDK or aw's workflow chaining) — coact is not LangGraph.

  • A running fleet is an optimization, not a default. Multi-agent fan-out costs roughly an order of magnitude more tokens, and the premium is worst on interdependent tasks. So backend="host" (one agent runs the skills) is the default, and coact estimate shows the tradeoff before you spawn a fleet:

    from coact import estimate
    print(estimate([agent_a, agent_b]).render())
    

    If you do decide to fan out, scaffold_fleet emits a starter Python shim wiring the realized agents under an aw coordinator — a sequential hand-off you then reshape. It's the one topology-adjacent thing coact writes, and only a starter: coact emits it once and never runs it (the topology stays yours).

    from coact import scaffold_fleet
    scaffold_fleet([agent_a, agent_b], dest="fleet.py")   # a runnable starter you own
    

Design notes

  • No LLM on any mechanical path; persona drafting is optional and injected (complete(skill, llm=...)), never a hard provider dependency.
  • Open-closed registries for emit targets (claude-agents-md, sdk-agent-dict, plus crewai / openai-tools auto-registered when aw is installed) and realization backends — register your own without touching core.
  • Decisions are recorded in misc/docs/DECISIONS.md; the build brief is misc/docs/COACT_SPEC.md.

Project details


Download files

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

Source Distribution

coact-0.0.4.tar.gz (122.7 kB view details)

Uploaded Source

Built Distribution

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

coact-0.0.4-py3-none-any.whl (60.6 kB view details)

Uploaded Python 3

File details

Details for the file coact-0.0.4.tar.gz.

File metadata

  • Download URL: coact-0.0.4.tar.gz
  • Upload date:
  • Size: 122.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for coact-0.0.4.tar.gz
Algorithm Hash digest
SHA256 4a4f8c9c362218a38823a29e171d5157aa0efbd4fa7f437c1531e16f136d1b69
MD5 8b5a94d08e86fc4cc9fa060b0494fcba
BLAKE2b-256 21b4ed8cb00969919d4d515a02b791729482cffc699d08e939b3c0f89eab5614

See more details on using hashes here.

File details

Details for the file coact-0.0.4-py3-none-any.whl.

File metadata

  • Download URL: coact-0.0.4-py3-none-any.whl
  • Upload date:
  • Size: 60.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for coact-0.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 5cef96017a651efb62c76677c429917272f69e00abe6c9decaaa797cc6257273
MD5 9ead51889e182fe70fe2fb788b03b867
BLAKE2b-256 1f55c059e5357adcda2ca11377ca18cfee40b21f63405cbe3775b39e79ecbcb0

See more details on using hashes here.

Supported by

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