kid-sid/claude-spellbook/agentex

Claude Code and agent skill by kid-sid/claude-spellbook

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Use when building, wiring, or debugging an Agentex agent — choosing agent type, configuring acp.py and manifest.yaml, using adk.messages or adk.state, or resolving Windows-specific setup issues.

Install

npx vskill@latest install kid-sid/claude-spellbook/agentex

SKILL.md

Agentex Platform

Agentex is a platform for building and deploying intelligent agents. The repo has two main parts:

  • agentex/ — FastAPI backend + Temporal workflows (runs in Docker)
  • agentex-ui/ — Next.js frontend (runs locally)

Agents are built with the agentex-sdk CLI and run as separate processes that register with the backend.

When to Activate

  • Choosing between sync, async, or Temporal agent type for a new agent
  • Wiring acp.py, manifest.yaml, or run_worker.py for a new agent
  • Using adk.messages, adk.state, or adk.providers in an activity or workflow
  • Debugging ACP protocol issues or agent registration failures
  • Understanding the backend DDD layer boundaries or exception mapping
  • Windows-specific setup issues (uv sync, port conflicts, .env loading)

Agent Types

Sync ACP

One message in, one response out. Stateless.

python
acp = FastACP.create(acp_type="sync")
@acp.on_message_send
async def handle(params: SendMessageParams) -> TaskMessageContent:
return TextContent(author="agent", content="reply")

Use when: FAQ bots, translation, data lookups, single-turn interactions.

Async ACP (base)

Task lifecycle with persistent state across multiple turns.

python
acp = FastACP.create(acp_type="async", config=AsyncACPConfig(type="base"))
@acp.on_task_create # called once — initialize state
@acp.on_task_event_send # called per message — respond via adk.messages.create
@acp.on_task_cancel # called on cancel — cleanup

Key difference from sync: responses are pushed via adk.messages.create, not returned. State is persisted via adk.state.create / get_by_task_and_agent / update.

Use when: multi-turn conversations, stateful workflows, streaming LLM responses. Warning: race conditions if parallel events arrive — use Temporal for production.

Async ACP + Temporal

Same as Async but every step is a durable Temporal workflow. Survives crashes and restarts.

yaml
# manifest.yaml
agent:
acp_type: async
temporal:
enabled: true

Use when: production agents, long-running tasks, human-in-the-loop, complex multi-step tool chains.


ACP State Pattern (Async)

python
class MyState(BaseModel):
turn: int
messages: List[Message]
# Create on task init
await adk.state.create(task_id=..., agent_id=..., state=MyState(...))
# Read on each event
task_state = await adk.state.get_by_task_and_agent(task_id=..., agent_id=...)
state = MyState.model_validate(task_state.state)
# Write back after mutating
await adk.state.update(state_id=task_state.id, task_id=..., agent_id=..., state=state)

Sending Messages (Async)

python
# Echo user message back (so it shows in UI)
await adk.messages.create(task_id=params.task.id, content=params.event.content)
# Send agent reply
await adk.messages.create(
task_id=params.task.id,
content=TextContent(author="agent", content="response text"),
)
# Streaming LLM (auto-sends chunks to UI)
await adk.providers.litellm.chat_completion_stream_auto_send(
task_id=params.task.id,
llm_config=LLMConfig(model="gpt-4o-mini", messages=state.messages, stream=True),
)

manifest.yaml Structure

yaml
local_development:
agent:
port: 8000 # must be unique per agent (8000, 8001, 8002...)
host_address: host.docker.internal
paths:
acp: project/acp.py
agent:
name: my-agent # unique name, shown in UI
acp_type: sync # or async
temporal:
enabled: false
credentials: []
env: {}

Backend Architecture

src/
├── api/routes/ # FastAPI endpoints
├── domain/entities/ # Pure Pydantic models
├── domain/use_cases/ # Business logic
├── adapters/crud_store/ # DB adapters (Postgres + MongoDB)
├── adapters/streams/ # Redis SSE streams
└── config/dependencies.py # Singleton GlobalDependencies

Layer rules:

  • Domain layer has zero framework imports
  • API layer → use cases → domain ← adapters
  • ORM ↔ domain conversion via explicit converter functions — never skip layers

Exceptions:

  • ClientError → 400, ServiceError → 500, ItemDoesNotExist → 404

Windows-Specific Gotchas

ProblemFix
uv sync fails: platform not compatibleAdd "sys_platform == 'win32'" to environments in root pyproject.toml, then uv lock
load_dotenv(override=True) clobbers Docker env varsChange to override=False in environment_variables.py
Local PostgreSQL on port 5432 blocks DockerChange Docker postgres port to 5434:5432 in docker-compose.yml
agentex init Unicode errorSet $env:PYTHONUTF8 = "1" before running
agentex init path has \n in itType short relative name (my-agent), not a full path
source .venv/bin/activate failsUse .venv\Scripts\Activate.ps1 on Windows
Temporal worker connects to localhost inside DockerCaused by .env overriding Docker network hostnames — needs override=False

Ports

PortService
3000Frontend UI
5003FastAPI backend (Swagger at /swagger)
5432Local PostgreSQL (if installed)
5434Docker agentex-postgres (remapped to avoid conflict)
5433Docker Temporal PostgreSQL
6379Redis
7233Temporal server
8080Temporal UI
8000+Agent ACP servers (one port per agent)
27017MongoDB

Key Environment Variables (agentex/.env)

env
ENVIRONMENT=development
DATABASE_URL=postgresql://postgres:postgres@127.0.0.1:5434/agentex
TEMPORAL_ADDRESS=localhost:7233
REDIS_URL=redis://localhost:6379
MONGODB_URI=mongodb://localhost:27017
MONGODB_DATABASE_NAME=agentex
AGENTEX_SERVER_TASK_QUEUE=agentex-server
ALLOWED_ORIGINS=http://localhost:3000
ENABLE_HEALTH_CHECK_WORKFLOW=true

Running Tests

powershell
cd agentex
# Unit tests (no Docker needed)
.\build.ps1 test-unit
# Integration tests (needs Docker infra running)
.\build.ps1 test-integration
# Specific file
.\build.ps1 test -File tests/unit/test_foo.py

Red Flags

  • Sync ACP for multi-turn conversations — sync agents receive one message and return one reply; they have no state, no turn history, and no mechanism to stream responses; use async ACP (or async + Temporal) for any stateful interaction
  • Handler decorators in `acp.py` for a Temporal agent — Temporal agents route all ACP events through the workflow engine; registering @acp.on_task_create decorators in acp.py bypasses Temporal and runs handlers outside the durable execution context
  • Returning a response from an async handler instead of using `adk.messages.create` — async agent handlers are not expected to return a value; the return value is silently discarded and the user sees no reply; push responses explicitly via adk.messages.create
  • Not following load → mutate → save with `adk.state` — reading state, mutating it in-memory, and then returning without saving means the next signal handler loads stale state; always call adk.state.update after every mutation before returning
  • Omitting `get_all_activities()` in `run_worker.py` — ADK built-in activities (messages, state persistence, tracing) are registered via get_all_activities(); omitting it means all adk.messages.create and adk.state.* calls fail at runtime with "activity not found"
  • Two agents sharing the same port in `manifest.yaml` — each ACP server process binds a port; running two agents with the same local_development.agent.port causes one to fail to start; increment the port for each agent (8000, 8001, 8002, …)
  • `load_dotenv(override=True)` when running inside Docker — overriding with the local .env file replaces Docker-injected environment variables such as DATABASE_URL and TEMPORAL_ADDRESS with localhost values, breaking service discovery inside the container network

Checklist

  • [ ] acp_type chosen correctly in manifest.yaml (sync / async / async + temporal)
  • [ ] Temporal agent acp.py has only FastACP.create(acp_type="async", config=TemporalACPConfig(...)) — no handler decorators
  • [ ] adk.messages.create used to send responses (not returned from handlers)
  • [ ] State follows load → mutate → save pattern via adk.state
  • [ ] on_task_create ends with await workflow.wait_condition(lambda: self._done) for Temporal agents
  • [ ] get_all_activities() included in worker alongside custom activities
  • [ ] Agent port in manifest.yaml is unique across all running agents (8000, 8001, …)
  • [ ] Windows: load_dotenv(override=False) to avoid clobbering Docker env vars
  • [ ] Domain exceptions (ClientError, ServiceError, ItemDoesNotExist) used — not HTTPException in use cases

Security

  • Security scanPassed, 95 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
186
Repository forks
15
7-day trend score
26

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/kid-sid/claude-spellbook/agentex/badge)](https://verified-skill.com/skills/kid-sid/claude-spellbook/agentex)

Something wrong with this skill or its page? Tell us.