This file is for AI coding agents (Claude Code, Cursor, Cline,
Aider, Windsurf, GitHub Copilot Workspace) that open this directory
and want to extend the Convilyn author SDK (convilyn-author) without
breaking it. Read this first; it documents the invariants that the
test suite will defend.
Consumer vs author: this is the SDK third-party developers use to build tool servers + workflow specs FOR Convilyn. The companion consumer SDK at
../consumer-python/(PyPIconvilyn) is what API callers use. They have separate__init__.py, separate PyPI identities, and separate CLI binaries (convilyn-authorhere,convilynthere).
sdk/author-python/ # PyPI: convilyn-author
├── pyproject.toml # one source of truth for deps + scripts
├── LICENSE # Apache-2.0
├── CHANGELOG.md # Keep-a-Changelog format
├── docs/
│ ├── README.md # PyPI landing page
│ └── DEPLOYMENT.md # Lambda / Fargate / VM walkthroughs + HMAC contract
├── examples/ # runnable example tool servers + workflows
├── src/convilyn_sdk/
│ ├── __init__.py # public surface — only re-exports
│ ├── _version.py # single source of truth for __version__
│ ├── server.py # ToolServer — the @server.tool decorator
│ ├── workflow.py # WorkflowSpec fluent builder
│ ├── workflow_types.py # v1 Pydantic siblings (Phase, Slot, ...)
│ ├── workflow_advanced_types.py # R3 critical: MultiAgent + Checkpoint
│ ├── workflow_policies.py # R3 high: TaskPolicy + Routing + QaPolicy
│ ├── policies.py # 5 high-level policy knobs (SemVer surface)
│ ├── workflow_validator.py # pre-submit dict-shape checks
│ ├── agent_role.py # AgentRole Protocol (DIP seam)
│ ├── client.py # ConvilynClient — push to platform
│ ├── manifest.py # ConvilynManifest — compiled blueprint
│ ├── catalog.py # ToolCatalog
│ ├── context.py # ToolContext
│ ├── config.py # SDKConfig — env-based configuration
│ ├── data_store.py # InMemoryDataStore + DataStoreProtocol
│ ├── types.py # ToolSpec / ToolError / ToolResult / ...
│ ├── testing/ # ConvilynTestRunner harness
│ ├── cli/
│ │ ├── main.py # Click CLI (`convilyn-author`)
│ │ └── scaffold.py # project scaffolding templates
│ └── _internal/ # NOT public — protocol, auth, server_runtime
└── tests/ # one test file per module
Anything reachable as from convilyn_sdk import X is public and
follows semver. Treat convilyn_sdk._internal.* as private — agents
can read it, but should not import from it in new tool servers or
examples.
These are the extension points. Use them; do not duplicate them.
| Seam | Purpose | Where |
|---|---|---|
@server.tool decorator |
Register a Python function as an MCP tool | server.py::ToolServer.tool |
WorkflowSpec fluent builder |
Compose a DestinationSpec declaratively |
workflow.py |
AgentRole Protocol |
DIP seam for with_multi_role — pass any object with role + optional tool_allowlist |
agent_role.py |
DataStoreProtocol |
Plug an alternative tool-result store (DynamoDB, S3, in-process …) | data_store.py |
ConvilynClient |
HMAC-signed HTTP client to push servers + workflows | client.py |
ConvilynTestRunner |
Local compliance + dry-run harness | testing/runner.py |
- Identify the backend
DestinationSpecfield you're surfacing (inbackend-api/app/models/goal_lane/destination.py). - If the field has structure (Pydantic siblings on the backend),
mirror it into
workflow_advanced_types.py(CRITICAL items) orworkflow_policies.py(HIGH items). Useextra="allow"so the backend can add fields without forcing an SDK bump (OCP). - Mirror any bounded
Literalvocabularies verbatim. Thetests/test_policy_literal_parity.pydrift detector will catch any divergence on monorepo CI. - Add the fluent method to
workflow.py, returning a clonedWorkflowSpec(immutable builder — see existing_clone()). - Thread the field through
compile()AND_from_dict()so round-trip works (WorkflowSpec.load(path).compile() == compiled). - Re-export new symbols from
convilyn_sdk/__init__.py. - Add 4-category tests (logic / boundary / error / object-state)
in a new
tests/test_workflow_<feature>.py. - Add a runnable example under
examples/<name>/workflow.py.
- Add the function in
cli/main.py(or extract into a sibling module if it grows beyond ~50 lines). - Register with
@cli.command()or@cli.group()— Click handles dispatch. - Re-use the standard scaffold:
_load_server_from_file(cli/main.py) for any command that touchesserver.py;_load_workflow_from_filefor workflow files. - Add a test mirroring the pattern in
tests/unit/cli/test_main.py(CliRunner for Click commands; sys.argv patching + capsys for any plain entry-point functions). - Update
docs/README.md's CLI table.
- No real backend calls in unit tests. Use
respxto mock HTTP (mirrors the consumer SDK convention) andtmp_pathfor filesystem. - Four categories per behaviour: logic, boundary, error, object-state. The unit-testing skill documents this in detail.
- Round-trip parity: every new
WorkflowSpecbuilder method must satisfy_from_dict(spec.compile()).compile() == spec.compile(). - Literal parity: any new
Literal[...]mirrored from the backend gets a row intests/test_policy_literal_parity.py. The test usespytest.importorskipso it cleanly skips when the backend isn't onsys.path(PyPI wheel CI), while running in monorepo CI.
from __future__ import annotationsat the top of every module so forward references just work.- Pydantic v2 with
populate_by_name=Trueso SDK fields use Python snake_case while the wire stays camelCase. ConfigDict(extra="allow")on every sibling Pydantic model — OCP forward-compat with backend additions.- Behaviour on the resource, data on the model — the OpenAI / Stripe convention. Do not put HTTP calls on the data models.
- Importing from
convilyn_sdk._internaloutside_internalandcli/. - Re-implementing HMAC verification —
_internal/auth.py::verify_signatureis the single source of truth. - Adding fluent methods that bypass the
_clone()immutability pattern. - Editing
__version__in__init__.py— bump_version.pyinstead. - Calling
time.sleepanywhere in async code paths (useawait asyncio.sleep).
- Read the relevant test file — the test names spell out the contract for the module.
convilyn-author doctorfor environment / connectivity issues.convilyn-author --helpfor the full command tree.- Open an issue at https://github.com/CoreNovus/convilyn/issues
with a minimal repro and the output of
convilyn-author doctor.
- Consumer SDK:
../consumer-python/AGENT.md(the SDK API callers use). - Deployment walkthroughs:
docs/DEPLOYMENT.md. - Public docs: https://docs.convilyn.com.