Skip to main content

Compile a declarative DAG of subagents into an orchestrated team on AWS Bedrock AgentCore.

Project description

Concursus

License: MIT Python 3.10+

Compile a declarative DAG of subagents into a deployed, orchestrated team on AWS Bedrock AgentCore.

Concursus (Latin "a running-together / convergence") is cursus's agent-orchestration sibling. Where cursus compiles a pipeline DAG + configs into a SageMaker pipeline, Concursus compiles an AgentDAG + per-agent .agent.yaml manifests into (1) an AgentCore provisioning plan — one CreateAgentRuntime per agent — and (2) a supervisor that dispatches the agents in topological order, wires each agent's declared output into its dependents' input, and routes shared state through AgentCore Memory.

It is the coordinator AgentCore deliberately doesn't ship: AgentCore gives you transport (A2A), tool discovery (Gateway), microVM isolation, identity, memory, and hosting — but no scheduler, dependency graph, or supervisor. You declare a DAG of agents; Concursus provisions them and runs them.

Status: alpha. This release ships the declarative core (AgentDAG + AgentManifest) and the offline compiler: the dependency resolver, the runtime builder, the OrchestrationAssembler (DAG + manifests → a ProvisioningPlan), and the topological Supervisor — plus the plan / deploy / run CLI verbs. The compiler is pure-Python; boto3 stays behind the [agentcore] extra and is imported lazily only when deploy --execute / run --execute actually calls AWS.


Installation

pip install concursus                 # declarative core (pure Python)
pip install "concursus[agentcore]"    # + the AWS Bedrock AgentCore runtime binding (roadmap)

Requires Python 3.10+.

Quick start

Declare a team as an AgentDAG (nodes = agents, edges = data dependencies):

from concursus import AgentDAG

dag = AgentDAG()
for agent in ["ingest", "summarize", "critique", "format"]:
    dag.add_node(agent)
dag.add_edge("ingest", "summarize")
dag.add_edge("summarize", "critique")
dag.add_edge("critique", "format")

dag.topological_sort()   # ['ingest', 'summarize', 'critique', 'format']  <- dispatch order
dag.validate()           # raises if the topology has a cycle

Describe each agent with an .agent.yaml manifest — its AgentCore binding + typed interface:

# summarize.agent.yaml
registry:
  container_uri: 111122223333.dkr.ecr.us-east-1.amazonaws.com/summarize-agent:latest
  role_arn: arn:aws:iam::111122223333:role/ConcursusAgentRuntimeRole
  network_mode: PUBLIC       # or VPC
  protocol: HTTP             # HTTP (/invocations) | MCP (/mcp) | A2A (/)
  qualifier: DEFAULT
  # ...or reuse an already-deployed agent:
  # agent_runtime_arn: arn:aws:bedrock-agentcore:us-east-1:111122223333:runtime/summarize-xyz
contract:
  inputs:
    document: {type: string}
  outputs:                   # required — the dependency resolver's type gate
    summary: {type: string}
    key_points: {type: array, items: {type: string}}
spec:
  depends_on:
    - {from: ingest.document, to: document}
from concursus import AgentManifest

m = AgentManifest.from_yaml("summarize.agent.yaml").validate()
m.protocol        # 'HTTP'
m.output_schema   # {'summary': {...}, 'key_points': {...}}

Or from the CLI:

concursus info                        # overview
concursus validate *.agent.yaml       # validate manifests
concursus --version

Compile a plan (plandeployrun)

Point the compiler at your manifests. Edges are inferred from each manifest's depends_on (or pass --dag ingest->summarize to set them explicitly). plan prints a JSON ProvisioningPlan — a topological order, one create_agent_runtime entry per agent, and the resolved producer→consumer wiring — without touching AWS:

concursus plan *.agent.yaml
from concursus import AgentDAG, AgentManifest, OrchestrationAssembler, Supervisor

manifests = {m.name: m for m in map(AgentManifest.from_yaml, paths)}
dag = AgentDAG()
for name in manifests:
    dag.add_node(name)
dag.add_edge("ingest", "summarize").add_edge("summarize", "critique")

plan = OrchestrationAssembler(account="111122223333", region="us-east-1").assemble(dag, manifests)
plan.order           # ['ingest', 'summarize', 'critique']  <- dispatch order
plan.to_dict()       # JSON-serializable preview (what `concursus plan` prints)

deploy dry-runs what would be created (no boto3 imported); --execute provisions each agent with CreateAgentRuntime on the control plane. run dry-runs the topological dispatch; --execute invokes the live runtimes, threading each output into its dependents:

concursus deploy *.agent.yaml                          # dry-run: what would be provisioned
concursus deploy *.agent.yaml --execute                # + boto3: CreateAgentRuntime on AWS
concursus run    *.agent.yaml --inputs '{"uri": "s3://doc"}'            # dry-run the dispatch
concursus run    *.agent.yaml --inputs @inputs.json --execute          # live InvokeAgentRuntime
outputs = Supervisor(plan, manifests).run({"uri": "s3://doc"})   # {node_id: output_dict}

How it works (the compile target)

Concursus compiles AgentDAG + manifests through validate → resolve → provision → assemble, mapping cursus concepts onto AgentCore primitives:

cursus Concursus AgentCore primitive
PipelineDAG AgentDAG dispatch order (topological)
.step.yaml .agent.yaml manifest container image + roleArn + protocol
DependencyType enum output JSON Schema (mandatory) the resolver's type gate
PropertyReference (deferred) AgentRef (eager JSONPath) InvokeAgentRuntime response
step registration agent registration CreateAgentRuntime → ARN + V1 + DEFAULT endpoint
PipelineAssemblerPipeline OrchestrationAssembler → supervisor + plan BedrockAgentCoreApp supervisor
S3 artifact channels shared run state AgentCore Memory

The supervisor dispatches agents in topological order, invokes each with InvokeAgentRuntime under one runtimeSessionId (session affinity → warm microVMs), extracts each producer's output by JSONPath and injects it into its consumers, and persists outputs to Memory so state survives the ephemeral microVMs.

Roadmap

  • Declarative core: AgentDAG + AgentManifest (.agent.yaml) + validation + CLI
  • Dependency resolver over declared output JSON Schemas (AgentRef wiring + type-gating)
  • OrchestrationAssembler: emit an AgentCore provisioning plan (CreateAgentRuntime per agent + synthesized IAM roles + endpoints)
  • The supervisor: topological dispatch over InvokeAgentRuntime with AgentRef wiring + one stable runtimeSessionId
  • plan / deploy / run CLI verbs (deploy/run --execute bind boto3 lazily)
  • Memory-backed shared run state (persist outputs across the ephemeral microVMs)
  • Gateway/A2A node types; a data-driven catalog + recommender of team topologies

License

MIT © Tianpei Xie

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

concursus-0.2.0.tar.gz (33.3 kB view details)

Uploaded Source

Built Distribution

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

concursus-0.2.0-py3-none-any.whl (27.4 kB view details)

Uploaded Python 3

File details

Details for the file concursus-0.2.0.tar.gz.

File metadata

  • Download URL: concursus-0.2.0.tar.gz
  • Upload date:
  • Size: 33.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.7

File hashes

Hashes for concursus-0.2.0.tar.gz
Algorithm Hash digest
SHA256 5a93d0dab243cc847cdc8307fb6a786c3388b3c598e837bf535da03c775986e2
MD5 29b32275c0ffef524084f2a7c45588db
BLAKE2b-256 d357ebc46a70d027479c74584fd7cdda86f6f4a1c35ac9d099bdc44ba4073885

See more details on using hashes here.

File details

Details for the file concursus-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: concursus-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 27.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.7

File hashes

Hashes for concursus-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d53f447f2e5999d5b7462f0873b61dc3deb570e62cdc15cd42cc86e9bb99a982
MD5 2b270bc8850ebe3eadb6cdf5b37a3626
BLAKE2b-256 65b955d03b6efa7e08834a5f8c326aa88c41a87a9d23b27c995a8da91ee10742

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