A terminal-first, Python-native SDK for turning SOPs into runnable agents with built-in human oversight
Project description
Proceda
Bring a procedure, get an agent.
Turn your team's Standard Operating Procedures into executable agents — without learning a framework, building a graph, or writing glue code. Proceda is a terminal-first Python SDK where a markdown file is the agent definition, human approval checkpoints are declarative, and every tool connection goes through MCP.
See it work
Write a procedure:
---
name: expense-processing
description: Process expense reports with policy validation
required_tools:
- receipts__extract
- erp__submit
---
### Step 1: Extract receipt data
Extract all receipt fields: date, vendor, amount, category, payment method.
### Step 2: Validate against policy
[APPROVAL REQUIRED]
Check against company policy. Flag violations.
- Single meals must not exceed $75
- Receipts older than 90 days are rejected
### Step 3: Submit to ERP
[PRE-APPROVAL REQUIRED]
Submit the approved expense report to the ERP system.
Run it:
proceda run ./expense-processing
The agent executes each step, calls tools via MCP, and pauses at the approval gates for human review. Every action is logged as a replayable JSONL event stream.
Why Proceda
Procedure is the source of truth
Not a prompt. Not a graph. Your SOP is the agent definition. Change the markdown, change the behavior. Non-technical teammates can read, review, and edit the procedure without touching code.
Human-in-the-loop is structural, not bolted on
Approval gates are declared with markers like [APPROVAL REQUIRED] and [PRE-APPROVAL REQUIRED]. The runtime enforces them. You don't write approval logic — you declare where humans must be involved.
MCP-native
Every tool connection uses the Model Context Protocol. No custom adapters, no vendor lock-in. The growing ecosystem of MCP servers — filesystem, databases, APIs, SaaS apps — is your tool library.
How it compares
| Proceda | LangGraph | CrewAI | AutoGen | |
|---|---|---|---|---|
| Agent definition | Markdown SOP | Python graph | Python classes | Python classes |
| Human approval | Declarative markers | Custom code | Limited | Custom code |
| Tool protocol | MCP (open standard) | Custom adapters | Custom adapters | Custom adapters |
| Replay / audit | Built-in JSONL logs | Manual | No | No |
| Learning curve | Write markdown | Learn graph API | Learn framework API | Learn framework API |
Architecture
SKILL.md ──→ Agent ──→ Runtime ──→ Executor ──→ LLM
│
├──→ MCP Tools (stdio / HTTP)
│
├──→ Human Interface (approve / clarify / recover)
│
└──→ Event Log (JSONL, replayable)
The runtime emits structured RunEvents at every transition. Events drive the CLI output, event logging, and SDK callbacks.
Install
pip install proceda
Or with uv:
uv add proceda
Quickstart
- Set your API key:
export ANTHROPIC_API_KEY=sk-...
- Run one of the included examples:
proceda run ./examples/toy-greeting --config examples/toy-greeting/proceda.yaml
- Configure your own tools in
proceda.yaml:
llm:
model: anthropic/claude-sonnet-4-20250514
apps:
- name: my-tools
description: My MCP tool server
transport: stdio
command: ["path/to/mcp-server"]
See proceda.yaml.example for the full reference, or read the configuration docs.
CLI
| Command | Description |
|---|---|
proceda run <path> |
Run a skill interactively in the terminal |
proceda lint <path> |
Validate a SKILL.md file |
proceda replay <run-id> |
Replay a previous run from its event log |
proceda doctor |
Check environment (Python, config, API keys, MCP servers) |
Python SDK
Synchronous
from proceda import Agent
agent = Agent.from_path("./my-skill")
result = agent.run()
print(result.status, result.summary)
Async with event streaming
from proceda import Agent
agent = Agent.from_path("./my-skill")
async for event in agent.run_stream():
print(event.type, event.payload)
Custom human interface
from proceda import Agent, HumanInterface
from proceda.session import ApprovalDecision
class SlackApprover(HumanInterface):
async def request_approval(self, request):
# Post to Slack, wait for reaction, return decision
return ApprovalDecision.APPROVE
async def request_clarification(self, request):
return "Proceed with defaults"
async def request_error_recovery(self, request):
return ErrorRecoveryDecision.RETRY
agent = Agent.from_path("./my-skill", human=SlackApprover())
result = await agent.run_async()
Skill format
---
name: workflow-name
description: What this workflow does
required_tools:
- app__tool_name
---
### Step 1: Do something
Instructions for the LLM.
### Step 2: Validate
[APPROVAL REQUIRED]
Human approves after this step completes.
### Step 3: Execute
[PRE-APPROVAL REQUIRED]
Human approves before this step begins.
### Step 4: Cleanup
[OPTIONAL]
Agent may skip this step if unnecessary.
Full reference: docs/skill-format.md
Examples
| Example | Runnable | Demonstrates |
|---|---|---|
| toy-greeting | Yes | Step progression, MCP tools, pre-approval gate |
| plan-week | With Google Workspace MCP | Real-world tool wiring |
| expense-processing | Illustrative | Policy validation, approval + pre-approval markers |
| change-management | Illustrative | Infrastructure ops, multiple approval gates, optional steps |
| support-escalation | Illustrative | Severity-based routing |
See examples/README.md for details.
Development
git clone https://github.com/vivekhaldar/proceda.git
cd proceda
uv sync --extra dev
make install-hooks
make check # lint + format + test + typecheck
Docs
License
Apache 2.0 — see LICENSE.
Built by Enchiridion Labs
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file proceda-0.1.1.tar.gz.
File metadata
- Download URL: proceda-0.1.1.tar.gz
- Upload date:
- Size: 245.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
34796f14d394154e7421104d495bf74d77fb1a7eb733cb897dde17e811339bd1
|
|
| MD5 |
ab7e40d04a2191b1af2417fc6679ad41
|
|
| BLAKE2b-256 |
74f52850df34dc0b47b6968a24dfc75d77635f3f753c3fcd8bfe21cb92a4e4e8
|
File details
Details for the file proceda-0.1.1-py3-none-any.whl.
File metadata
- Download URL: proceda-0.1.1-py3-none-any.whl
- Upload date:
- Size: 56.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
32893299251c1342062103129e0ba719d9fac97d45839b290d2bcf89daef3025
|
|
| MD5 |
3a731d958c7bdf32bc8bd6fc3c4502e8
|
|
| BLAKE2b-256 |
f835176006bc8706f55a26f8b82125e90621628093a073636440018981705a64
|