conducto-ai 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- conducto_ai-0.1.0/.gitignore +35 -0
- conducto_ai-0.1.0/LICENSE +15 -0
- conducto_ai-0.1.0/PKG-INFO +42 -0
- conducto_ai-0.1.0/README.md +207 -0
- conducto_ai-0.1.0/docs/README.md +52 -0
- conducto_ai-0.1.0/pyproject.toml +89 -0
- conducto_ai-0.1.0/src/conducto/__init__.py +38 -0
- conducto_ai-0.1.0/src/conducto/a2a/__init__.py +115 -0
- conducto_ai-0.1.0/src/conducto/adapters/__init__.py +29 -0
- conducto_ai-0.1.0/src/conducto/adapters/catalog.py +157 -0
- conducto_ai-0.1.0/src/conducto/core/__init__.py +5 -0
- conducto_ai-0.1.0/src/conducto/core/a2a_profile.py +178 -0
- conducto_ai-0.1.0/src/conducto/core/agent.py +184 -0
- conducto_ai-0.1.0/src/conducto/core/agent_card.py +485 -0
- conducto_ai-0.1.0/src/conducto/core/catalog/__init__.py +49 -0
- conducto_ai-0.1.0/src/conducto/core/catalog/_admission.py +134 -0
- conducto_ai-0.1.0/src/conducto/core/catalog/_lifecycle.py +541 -0
- conducto_ai-0.1.0/src/conducto/core/catalog/_managed.py +345 -0
- conducto_ai-0.1.0/src/conducto/core/catalog/_managed_models.py +74 -0
- conducto_ai-0.1.0/src/conducto/core/catalog/_models.py +274 -0
- conducto_ai-0.1.0/src/conducto/core/catalog/_providers.py +119 -0
- conducto_ai-0.1.0/src/conducto/core/decorators.py +372 -0
- conducto_ai-0.1.0/src/conducto/core/delegation/__init__.py +26 -0
- conducto_ai-0.1.0/src/conducto/core/delegation/_arguments.py +137 -0
- conducto_ai-0.1.0/src/conducto/core/delegation/_fallback.py +54 -0
- conducto_ai-0.1.0/src/conducto/core/delegation/_loop.py +408 -0
- conducto_ai-0.1.0/src/conducto/core/delegation/_models.py +164 -0
- conducto_ai-0.1.0/src/conducto/core/delegation/_results.py +89 -0
- conducto_ai-0.1.0/src/conducto/core/gateway/__init__.py +25 -0
- conducto_ai-0.1.0/src/conducto/core/gateway/_bindings.py +167 -0
- conducto_ai-0.1.0/src/conducto/core/gateway/_contracts.py +131 -0
- conducto_ai-0.1.0/src/conducto/core/gateway/_discovery.py +137 -0
- conducto_ai-0.1.0/src/conducto/core/gateway/_hybrid.py +677 -0
- conducto_ai-0.1.0/src/conducto/core/gateway/_local.py +451 -0
- conducto_ai-0.1.0/src/conducto/core/gateway/_projection.py +105 -0
- conducto_ai-0.1.0/src/conducto/core/gateway/_schema.py +230 -0
- conducto_ai-0.1.0/src/conducto/core/gateway_models.py +295 -0
- conducto_ai-0.1.0/src/conducto/core/gateway_tools.py +394 -0
- conducto_ai-0.1.0/src/conducto/core/invocation.py +484 -0
- conducto_ai-0.1.0/src/conducto/core/invocation_results.py +235 -0
- conducto_ai-0.1.0/src/conducto/core/logging.py +315 -0
- conducto_ai-0.1.0/src/conducto/core/model_config.py +180 -0
- conducto_ai-0.1.0/src/conducto/core/model_gateway.py +302 -0
- conducto_ai-0.1.0/src/conducto/core/model_resolution.py +186 -0
- conducto_ai-0.1.0/src/conducto/core/orchestrator.py +369 -0
- conducto_ai-0.1.0/src/conducto/core/otel_logs.py +285 -0
- conducto_ai-0.1.0/src/conducto/core/parameter_schema.py +117 -0
- conducto_ai-0.1.0/src/conducto/core/provider/__init__.py +111 -0
- conducto_ai-0.1.0/src/conducto/core/provider/_json.py +27 -0
- conducto_ai-0.1.0/src/conducto/core/provider/configuration.py +53 -0
- conducto_ai-0.1.0/src/conducto/core/provider/decisions.py +194 -0
- conducto_ai-0.1.0/src/conducto/core/provider/errors.py +236 -0
- conducto_ai-0.1.0/src/conducto/core/provider/execution.py +153 -0
- conducto_ai-0.1.0/src/conducto/core/provider/messages.py +48 -0
- conducto_ai-0.1.0/src/conducto/core/provider/protocol.py +197 -0
- conducto_ai-0.1.0/src/conducto/core/provider/results.py +77 -0
- conducto_ai-0.1.0/src/conducto/core/provider/structured.py +225 -0
- conducto_ai-0.1.0/src/conducto/core/provider/tools.py +179 -0
- conducto_ai-0.1.0/src/conducto/core/provider_registry/__init__.py +32 -0
- conducto_ai-0.1.0/src/conducto/core/provider_registry/availability.py +29 -0
- conducto_ai-0.1.0/src/conducto/core/provider_registry/bindings.py +279 -0
- conducto_ai-0.1.0/src/conducto/core/provider_registry/cleanup.py +260 -0
- conducto_ai-0.1.0/src/conducto/core/provider_registry/configuration.py +64 -0
- conducto_ai-0.1.0/src/conducto/core/provider_registry/factories.py +88 -0
- conducto_ai-0.1.0/src/conducto/core/provider_registry/lifecycle.py +255 -0
- conducto_ai-0.1.0/src/conducto/core/provider_registry/ownership.py +87 -0
- conducto_ai-0.1.0/src/conducto/core/provider_registry/registration.py +23 -0
- conducto_ai-0.1.0/src/conducto/core/provider_registry/registry.py +13 -0
- conducto_ai-0.1.0/src/conducto/core/provider_registry/snapshots.py +77 -0
- conducto_ai-0.1.0/src/conducto/core/provider_registry/state.py +44 -0
- conducto_ai-0.1.0/src/conducto/core/registration.py +227 -0
- conducto_ai-0.1.0/src/conducto/core/registry.py +473 -0
- conducto_ai-0.1.0/src/conducto/core/run_context.py +590 -0
- conducto_ai-0.1.0/src/conducto/core/runtime.py +529 -0
- conducto_ai-0.1.0/src/conducto/core/runtime_context.py +115 -0
- conducto_ai-0.1.0/src/conducto/core/runtime_errors.py +108 -0
- conducto_ai-0.1.0/src/conducto/core/runtime_invocation.py +165 -0
- conducto_ai-0.1.0/src/conducto/core/serialization.py +83 -0
- conducto_ai-0.1.0/src/conducto/core/telemetry.py +379 -0
- conducto_ai-0.1.0/src/conducto/mcp/__init__.py +118 -0
- conducto_ai-0.1.0/src/conducto/mcp/errors.py +52 -0
- conducto_ai-0.1.0/src/conducto/mcp/export.py +342 -0
- conducto_ai-0.1.0/src/conducto/mcp/http.py +498 -0
- conducto_ai-0.1.0/src/conducto/mcp/mapping.py +148 -0
- conducto_ai-0.1.0/src/conducto/mcp/naming.py +61 -0
- conducto_ai-0.1.0/src/conducto/mcp/policy.py +165 -0
- conducto_ai-0.1.0/src/conducto/mcp/profile.py +97 -0
- conducto_ai-0.1.0/src/conducto/mcp/schema.py +283 -0
- conducto_ai-0.1.0/src/conducto/mcp/server.py +289 -0
- conducto_ai-0.1.0/src/conducto/providers/__init__.py +62 -0
- conducto_ai-0.1.0/src/conducto/providers/_config.py +157 -0
- conducto_ai-0.1.0/src/conducto/providers/_http.py +168 -0
- conducto_ai-0.1.0/src/conducto/providers/_lifecycle.py +39 -0
- conducto_ai-0.1.0/src/conducto/providers/_response.py +264 -0
- conducto_ai-0.1.0/src/conducto/providers/_schema.py +50 -0
- conducto_ai-0.1.0/src/conducto/providers/_tool_cache.py +44 -0
- conducto_ai-0.1.0/src/conducto/providers/ollama.py +760 -0
- conducto_ai-0.1.0/src/conducto/providers/openai_compatible.py +998 -0
- conducto_ai-0.1.0/src/conducto/registration/__init__.py +33 -0
- conducto_ai-0.1.0/src/conducto/registration/asgi.py +298 -0
- conducto_ai-0.1.0/src/conducto/registration/client.py +250 -0
- conducto_ai-0.1.0/src/conducto/registration/models.py +179 -0
- conducto_ai-0.1.0/src/conducto/registration/policy.py +88 -0
- conducto_ai-0.1.0/src/conducto/registration/service.py +409 -0
- conducto_ai-0.1.0/src/conducto/security/__init__.py +209 -0
- conducto_ai-0.1.0/src/conducto/security/approval.py +328 -0
- conducto_ai-0.1.0/src/conducto/security/approval_token.py +286 -0
- conducto_ai-0.1.0/src/conducto/security/audit.py +393 -0
- conducto_ai-0.1.0/src/conducto/security/context.py +119 -0
- conducto_ai-0.1.0/src/conducto/security/crypto.py +303 -0
- conducto_ai-0.1.0/src/conducto/security/errors.py +115 -0
- conducto_ai-0.1.0/src/conducto/security/guardrails.py +147 -0
- conducto_ai-0.1.0/src/conducto/security/pipeline.py +511 -0
- conducto_ai-0.1.0/src/conducto/security/tokens.py +555 -0
- conducto_ai-0.1.0/src/conducto/security/trust.py +145 -0
- conducto_ai-0.1.0/src/conducto/testing/__init__.py +28 -0
- conducto_ai-0.1.0/src/conducto/testing/a2a_transport.py +131 -0
- conducto_ai-0.1.0/src/conducto/testing/fake_model.py +120 -0
- conducto_ai-0.1.0/src/conducto/testing/provider_conformance.py +231 -0
- conducto_ai-0.1.0/src/conducto/transport/__init__.py +51 -0
- conducto_ai-0.1.0/src/conducto/transport/a2a.py +330 -0
- conducto_ai-0.1.0/src/conducto/transport/auth.py +350 -0
- conducto_ai-0.1.0/src/conducto/transport/errors.py +33 -0
- conducto_ai-0.1.0/src/conducto/transport/tasks.py +156 -0
- conducto_ai-0.1.0/src/conducto/transport/tls.py +131 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Python bytecode
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.pyo
|
|
5
|
+
*.pyd
|
|
6
|
+
|
|
7
|
+
# Virtual environments
|
|
8
|
+
.venv/
|
|
9
|
+
venv/
|
|
10
|
+
ENV/
|
|
11
|
+
env/
|
|
12
|
+
|
|
13
|
+
# Packaging/build output
|
|
14
|
+
build/
|
|
15
|
+
dist/
|
|
16
|
+
*.egg
|
|
17
|
+
*.egg-info/
|
|
18
|
+
.eggs/
|
|
19
|
+
|
|
20
|
+
# Testing and coverage
|
|
21
|
+
.pytest_cache/
|
|
22
|
+
.coverage
|
|
23
|
+
.coverage.*
|
|
24
|
+
htmlcov/
|
|
25
|
+
.tox/
|
|
26
|
+
.nox/
|
|
27
|
+
reports/
|
|
28
|
+
.smoke-venv/
|
|
29
|
+
|
|
30
|
+
# IDE/editor files
|
|
31
|
+
.idea/
|
|
32
|
+
.vscode/
|
|
33
|
+
|
|
34
|
+
# Local tool caches
|
|
35
|
+
.uv/
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Apache 2.0 License
|
|
2
|
+
|
|
3
|
+
Copyright 2026 Malcolm Miller
|
|
4
|
+
|
|
5
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
you may not use this file except in compliance with the License.
|
|
7
|
+
You may obtain a copy of the License at
|
|
8
|
+
|
|
9
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
|
|
11
|
+
Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
See the License for the specific language governing permissions and
|
|
15
|
+
limitations under the License.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: conducto-ai
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
License: Apache 2.0 License
|
|
5
|
+
|
|
6
|
+
Copyright 2026 Malcolm Miller
|
|
7
|
+
|
|
8
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
9
|
+
you may not use this file except in compliance with the License.
|
|
10
|
+
You may obtain a copy of the License at
|
|
11
|
+
|
|
12
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
13
|
+
|
|
14
|
+
Unless required by applicable law or agreed to in writing, software
|
|
15
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
+
See the License for the specific language governing permissions and
|
|
18
|
+
limitations under the License.
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Python: >=3.12
|
|
21
|
+
Requires-Dist: a2a-sdk==1.1.5
|
|
22
|
+
Requires-Dist: cryptography>=44.0.0
|
|
23
|
+
Requires-Dist: packaging>=24.0
|
|
24
|
+
Requires-Dist: pydantic>=2.13.5
|
|
25
|
+
Provides-Extra: mcp
|
|
26
|
+
Requires-Dist: mcp==2.2.0; extra == 'mcp'
|
|
27
|
+
Provides-Extra: microsoft-foundry
|
|
28
|
+
Requires-Dist: azure-ai-projects>=1.0.0b11; extra == 'microsoft-foundry'
|
|
29
|
+
Requires-Dist: azure-identity>=1.17; extra == 'microsoft-foundry'
|
|
30
|
+
Provides-Extra: ollama
|
|
31
|
+
Requires-Dist: httpx<1.0,>=0.28.1; extra == 'ollama'
|
|
32
|
+
Requires-Dist: ollama>=0.5; extra == 'ollama'
|
|
33
|
+
Provides-Extra: openai
|
|
34
|
+
Requires-Dist: httpx<1.0,>=0.28.1; extra == 'openai'
|
|
35
|
+
Requires-Dist: openai>=1.0; extra == 'openai'
|
|
36
|
+
Provides-Extra: opentelemetry
|
|
37
|
+
Requires-Dist: opentelemetry-api==1.37.0; extra == 'opentelemetry'
|
|
38
|
+
Requires-Dist: opentelemetry-sdk==1.37.0; extra == 'opentelemetry'
|
|
39
|
+
Provides-Extra: registration
|
|
40
|
+
Requires-Dist: httpx<1.0,>=0.28.1; extra == 'registration'
|
|
41
|
+
Provides-Extra: test
|
|
42
|
+
Requires-Dist: pytest>=9.1.1; extra == 'test'
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Conducto
|
|
2
|
+
|
|
3
|
+
Conducto is a capability-first Python framework for building governed multi-agent systems.
|
|
4
|
+
|
|
5
|
+
The project is designed around a simple goal: define an agent capability once, then discover and
|
|
6
|
+
invoke it through the same typed contract whether the target runs in the current process, behind an
|
|
7
|
+
A2A endpoint, in a container, or in Microsoft Foundry. Deployment should change configuration and
|
|
8
|
+
transport—not agent business logic.
|
|
9
|
+
|
|
10
|
+
## Why Conducto?
|
|
11
|
+
|
|
12
|
+
Agent systems often couple model prompts, tool definitions, service discovery, networking, and
|
|
13
|
+
authorization into one runtime. That makes agent-to-agent calls difficult to test, secure, and move
|
|
14
|
+
between environments.
|
|
15
|
+
|
|
16
|
+
Conducto separates those responsibilities:
|
|
17
|
+
|
|
18
|
+
- **Typed capabilities:** Python decorators reflect regular methods into validated capability
|
|
19
|
+
schemas and deterministic Agent Cards.
|
|
20
|
+
- **Provider-neutral models:** Agents use opaque model references and structured-output contracts
|
|
21
|
+
instead of importing vendor SDKs.
|
|
22
|
+
- **Governed execution:** Authorization, approvals, audit, deadlines, cancellation, and typed
|
|
23
|
+
failures surround capability execution.
|
|
24
|
+
- **Capability-first discovery:** Callers ask for an allowed capability rather than hardcoding a
|
|
25
|
+
particular deployment.
|
|
26
|
+
- **Transport-independent invocation:** Local and remote calls share validation, context,
|
|
27
|
+
serialization, and result semantics.
|
|
28
|
+
- **Portable deployments:** The same agent contract is intended to progress from one process to
|
|
29
|
+
containers, Microsoft Foundry, and optional cross-organization federation.
|
|
30
|
+
- **Protocol conformance:** Checked-in schemas and fixtures pin observable wire behavior.
|
|
31
|
+
|
|
32
|
+
## What Conducto is for
|
|
33
|
+
|
|
34
|
+
Conducto is intended for systems where an application must coordinate specialized agents without
|
|
35
|
+
giving every model unrestricted access to every tool or deployment:
|
|
36
|
+
|
|
37
|
+
- an operations agent that delegates evidence gathering to documentation and diagnostic agents
|
|
38
|
+
- a business workflow that requires scoped authority and human approval before protected actions
|
|
39
|
+
- a local agent composition that later moves behind authenticated network boundaries
|
|
40
|
+
- a hybrid deployment that combines in-process, containerized, and Foundry-hosted agents
|
|
41
|
+
- independently deployed Python agents that must follow the same observable contract
|
|
42
|
+
|
|
43
|
+
Conducto is not intended to be another general-purpose chat UI or a vendor-specific model wrapper.
|
|
44
|
+
Its primary concern is the controlled discovery, delegation, and execution of typed agent
|
|
45
|
+
capabilities.
|
|
46
|
+
|
|
47
|
+
## Current status
|
|
48
|
+
|
|
49
|
+
The repository currently develops the **pre-v1 Python reference SDK** directly from the repository
|
|
50
|
+
root.
|
|
51
|
+
Implemented foundations include:
|
|
52
|
+
|
|
53
|
+
- `@a2a_agent`, `@a2a_capability`, and `@tool` metadata
|
|
54
|
+
- deterministic Agent Card generation
|
|
55
|
+
- local agent registration, policy-filtered discovery, and opaque capability bindings
|
|
56
|
+
- model-mediated routing and bounded model-selected delegation
|
|
57
|
+
- validated capability invocation and typed result envelopes
|
|
58
|
+
- provider-neutral model configuration and per-run model isolation
|
|
59
|
+
- authorization scopes and approval challenges
|
|
60
|
+
- structured, correlation-safe runtime logging
|
|
61
|
+
- pinned A2A 1.0 transport and governed remote-agent catalog contracts
|
|
62
|
+
- bounded Ollama and OpenAI-compatible provider adapters
|
|
63
|
+
- optional MCP export and OpenTelemetry integration
|
|
64
|
+
|
|
65
|
+
Container deployment, Foundry integration, durable workflow orchestration, and federation remain
|
|
66
|
+
roadmap work. No v1 API has shipped: common application entry points live in
|
|
67
|
+
`conducto`, specialized contracts in their owning `conducto.core` packages, and deterministic
|
|
68
|
+
test providers in `conducto.testing`.
|
|
69
|
+
|
|
70
|
+
## Intended execution model
|
|
71
|
+
|
|
72
|
+
```mermaid
|
|
73
|
+
flowchart LR
|
|
74
|
+
U[Application or user] --> O[Orchestrator]
|
|
75
|
+
O --> G[Agent gateway]
|
|
76
|
+
G --> P[Policy-filtered capability discovery]
|
|
77
|
+
P --> L[Local agent]
|
|
78
|
+
P --> R[Remote A2A agent]
|
|
79
|
+
P --> F[Foundry-hosted agent]
|
|
80
|
+
|
|
81
|
+
L --> X[Shared invocation pipeline]
|
|
82
|
+
R --> X
|
|
83
|
+
F --> X
|
|
84
|
+
|
|
85
|
+
X --> V[Validation and guardrails]
|
|
86
|
+
V --> E[Capability execution]
|
|
87
|
+
E --> T[Typed result and provenance]
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The registry/catalog describes what agents exist. The gateway decides which eligible target and
|
|
91
|
+
transport to use. The runtime owns execution context, model resolution, security, auditing,
|
|
92
|
+
deadlines, cancellation, and results. Keeping these boundaries separate allows local behavior to
|
|
93
|
+
remain the reference for every later deployment.
|
|
94
|
+
|
|
95
|
+
## Python quick start
|
|
96
|
+
|
|
97
|
+
Requirements: Python 3.12 or newer and [`uv`](https://docs.astral.sh/uv/).
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
uv sync --locked --group dev
|
|
101
|
+
uv run python examples/quickstart.py
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
A minimal capability looks like:
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from conducto import BaseAgent, a2a_agent, a2a_capability
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@a2a_agent(
|
|
111
|
+
name="InventoryAgent",
|
|
112
|
+
version="1.0.0",
|
|
113
|
+
description="Answers inventory questions.",
|
|
114
|
+
)
|
|
115
|
+
class InventoryAgent(BaseAgent):
|
|
116
|
+
@a2a_capability(description="Return the available quantity for one SKU.")
|
|
117
|
+
def get_quantity(self, sku: str) -> dict[str, object]:
|
|
118
|
+
return {"sku": sku, "quantity": 12}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
For a complete installed-package verification:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
uv run pytest -m acceptance
|
|
125
|
+
uv build
|
|
126
|
+
wheel=$(ls dist/*.whl)
|
|
127
|
+
uv run --no-project --with "$wheel" python examples/quickstart.py
|
|
128
|
+
uv run --no-project --with "$wheel" python scripts/smoke_test.py
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Optional integrations are installed with package extras such as
|
|
132
|
+
`conducto-ai[registration]`, `conducto-ai[mcp]`, `conducto-ai[ollama]`,
|
|
133
|
+
`conducto-ai[openai]`, `conducto-ai[microsoft-foundry]`, and
|
|
134
|
+
`conducto-ai[opentelemetry]`.
|
|
135
|
+
|
|
136
|
+
## Architecture principles
|
|
137
|
+
|
|
138
|
+
1. **Python and contracts first.** Python establishes the reference behavior.
|
|
139
|
+
2. **Local before remote.** In-process execution establishes semantics before network transport.
|
|
140
|
+
3. **Capabilities before endpoints.** Agent code targets compatible capabilities, not deployment
|
|
141
|
+
addresses.
|
|
142
|
+
4. **Policy before model exposure.** Unauthorized or incompatible tools never enter a model's
|
|
143
|
+
toolbox.
|
|
144
|
+
5. **No authority amplification.** Delegation can preserve or reduce scopes, budgets, and
|
|
145
|
+
deadlines, never expand them.
|
|
146
|
+
6. **Typed failures over hidden fallbacks.** Transport, policy, validation, approval, timeout, and
|
|
147
|
+
execution failures remain distinguishable.
|
|
148
|
+
7. **Local reproducibility.** Core behavior must remain usable without cloud credentials, network
|
|
149
|
+
services, or model downloads.
|
|
150
|
+
|
|
151
|
+
Read the [Python SDK architecture](./docs/architecture.md),
|
|
152
|
+
[security model](./docs/security-and-governance.md), and
|
|
153
|
+
[deployment topology guide](./docs/deployment-and-federation.md) for details.
|
|
154
|
+
|
|
155
|
+
## Roadmap
|
|
156
|
+
|
|
157
|
+
The active roadmap is tracked in [GitHub milestones](https://github.com/malcmiller/conducto-ai/milestones):
|
|
158
|
+
|
|
159
|
+
1. Python local agent flow
|
|
160
|
+
2. Python security and governance
|
|
161
|
+
3. Python agent chaining and local gateway
|
|
162
|
+
4. Python A2A network transport
|
|
163
|
+
5. Python exporters, observability, and packaging
|
|
164
|
+
6. Python model runtimes and Microsoft Foundry
|
|
165
|
+
7. Python hybrid deployment and workflow orchestration
|
|
166
|
+
8. Cross-organization federation
|
|
167
|
+
|
|
168
|
+
The required product progression is **local Python → governed Python chaining → Python network
|
|
169
|
+
transport → operational packaging → containers and Foundry → hybrid workflows → optional
|
|
170
|
+
federation**.
|
|
171
|
+
|
|
172
|
+
## Repository layout
|
|
173
|
+
|
|
174
|
+
```text
|
|
175
|
+
.
|
|
176
|
+
├── src/conducto/ Python package
|
|
177
|
+
├── tests/ Unit, acceptance, and golden tests
|
|
178
|
+
├── examples/ Runnable application examples
|
|
179
|
+
├── scripts/ Release and installed-package verification
|
|
180
|
+
├── docs/ Product and SDK documentation
|
|
181
|
+
├── pyproject.toml Package and tool configuration
|
|
182
|
+
└── uv.lock Reproducible dependency lock
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Documentation
|
|
186
|
+
|
|
187
|
+
- [Documentation index](./docs/README.md)
|
|
188
|
+
- [Python SDK architecture](./docs/architecture.md)
|
|
189
|
+
- [Python SDK reference](./docs/sdk-reference.md)
|
|
190
|
+
- [Python security and governance](./docs/security-and-governance.md)
|
|
191
|
+
- [Communication and standards](./docs/communication-and-standards.md)
|
|
192
|
+
- [Deployment and federation](./docs/deployment-and-federation.md)
|
|
193
|
+
- [Repository automation and agent guidance](./docs/repository-automation.md)
|
|
194
|
+
- [Development guide](./docs/development-guide.md)
|
|
195
|
+
- [Release guide](./docs/releasing.md)
|
|
196
|
+
|
|
197
|
+
## Contributing
|
|
198
|
+
|
|
199
|
+
Choose an issue from the [roadmap](https://github.com/malcmiller/conducto-ai/issues), confirm its
|
|
200
|
+
dependencies are complete, and keep implementation aligned with its acceptance criteria. See the
|
|
201
|
+
[Python SDK development guide](./docs/development-guide.md) for setup and validation and
|
|
202
|
+
[repository automation documentation](./docs/repository-automation.md) for agent instructions and
|
|
203
|
+
workflows.
|
|
204
|
+
|
|
205
|
+
## License
|
|
206
|
+
|
|
207
|
+
Conducto is licensed under the [Apache License 2.0](./LICENSE).
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Conducto repository documentation
|
|
2
|
+
|
|
3
|
+
This directory contains product, protocol, deployment, automation, and Python
|
|
4
|
+
SDK documentation for the flattened Python-only repository.
|
|
5
|
+
|
|
6
|
+
## What this repository contains
|
|
7
|
+
|
|
8
|
+
- `README.md` at the repository root introduces the Conducto vision and roadmap.
|
|
9
|
+
- `src/conducto/` contains the shipped Python package (`conducto-ai`).
|
|
10
|
+
- `docs/` documents the product, implementation, and public API.
|
|
11
|
+
- `tests/` records expected behavior through unit, golden, and acceptance tests.
|
|
12
|
+
|
|
13
|
+
## Documentation map
|
|
14
|
+
|
|
15
|
+
- [Repository overview](./repository-overview.md) — repository purpose, structure, and key concepts.
|
|
16
|
+
- [Communication paths and standards](./communication-and-standards.md) — A2A sequencing, local orchestration, container transport, and Microsoft Foundry-based model routing.
|
|
17
|
+
- [Conducto A2A 1.0 profile](./a2a-1-profile.md) — pinned protocol provenance, feature matrix, compatibility policy, conformance fixtures, and update procedure.
|
|
18
|
+
- [Deployment topologies and federation](./deployment-and-federation.md) — local, container, Foundry, hybrid, and cross-organization scenarios plus ownership, trust, catalog, and workflow orchestration.
|
|
19
|
+
- [Repository automation and agent guidance](./repository-automation.md) — coding-agent instructions, required validation, CI behavior, branch protection, and workflow maintenance.
|
|
20
|
+
- [Architecture](./architecture.md) — component boundaries and end-to-end data flow.
|
|
21
|
+
- [SDK reference](./sdk-reference.md) — supported public imports and API contracts.
|
|
22
|
+
- [Development guide](./development-guide.md) — local validation and contribution workflow.
|
|
23
|
+
- [Releasing](./releasing.md) — trusted publishing, rehearsal, verification, and recovery.
|
|
24
|
+
- [Agents and registration](./agents-and-registration.md)
|
|
25
|
+
- [Gateway and discovery](./gateway-and-discovery.md)
|
|
26
|
+
- [Orchestration and delegation](./orchestration-and-delegation.md)
|
|
27
|
+
- [Providers and models](./providers-and-models.md)
|
|
28
|
+
- [Runtime and invocation](./runtime-and-invocation.md)
|
|
29
|
+
- [Security and governance](./security-and-governance.md)
|
|
30
|
+
|
|
31
|
+
## Quick start
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
from conducto import BaseAgent, a2a_agent, a2a_capability
|
|
35
|
+
|
|
36
|
+
@a2a_agent(name="AuditAgent", version="1.0", description="Evaluates transaction risk.")
|
|
37
|
+
class AuditAgent(BaseAgent):
|
|
38
|
+
@a2a_capability(description="Evaluates transaction risk against compliance rules.")
|
|
39
|
+
def evaluate_transaction_risk(self, vendor_id: str, amount: float) -> dict:
|
|
40
|
+
return {
|
|
41
|
+
"vendor_id": vendor_id,
|
|
42
|
+
"status": "APPROVED",
|
|
43
|
+
"risk_score": 0.05,
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The Python SDK uses structured metadata to reflect methods into A2A-compatible
|
|
48
|
+
Agent Cards and deterministic routing payloads.
|
|
49
|
+
|
|
50
|
+
## Scope note
|
|
51
|
+
|
|
52
|
+
The implementation and repository are Python-only.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[tool.hatch.build.targets.wheel]
|
|
6
|
+
packages = ["src/conducto"]
|
|
7
|
+
|
|
8
|
+
[tool.hatch.build.targets.sdist]
|
|
9
|
+
include = ["src/conducto", "README.md", "LICENSE", "pyproject.toml"]
|
|
10
|
+
|
|
11
|
+
[project]
|
|
12
|
+
name = "conducto-ai"
|
|
13
|
+
version = "0.1.0"
|
|
14
|
+
requires-python = ">=3.12"
|
|
15
|
+
license = { file = "LICENSE" }
|
|
16
|
+
dependencies = [
|
|
17
|
+
"a2a-sdk==1.1.5",
|
|
18
|
+
"cryptography>=44.0.0",
|
|
19
|
+
"packaging>=24.0",
|
|
20
|
+
"pydantic>=2.13.5",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[project.optional-dependencies]
|
|
24
|
+
registration = [
|
|
25
|
+
"httpx>=0.28.1,<1.0",
|
|
26
|
+
]
|
|
27
|
+
mcp = [
|
|
28
|
+
"mcp==2.2.0",
|
|
29
|
+
]
|
|
30
|
+
ollama = [
|
|
31
|
+
"httpx>=0.28.1,<1.0",
|
|
32
|
+
"ollama>=0.5",
|
|
33
|
+
]
|
|
34
|
+
openai = [
|
|
35
|
+
"httpx>=0.28.1,<1.0",
|
|
36
|
+
"openai>=1.0",
|
|
37
|
+
]
|
|
38
|
+
microsoft-foundry = [
|
|
39
|
+
"azure-ai-projects>=1.0.0b11",
|
|
40
|
+
"azure-identity>=1.17",
|
|
41
|
+
]
|
|
42
|
+
test = [
|
|
43
|
+
"pytest>=9.1.1",
|
|
44
|
+
]
|
|
45
|
+
opentelemetry = [
|
|
46
|
+
"opentelemetry-api==1.37.0",
|
|
47
|
+
"opentelemetry-sdk==1.37.0",
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
[dependency-groups]
|
|
51
|
+
dev = [
|
|
52
|
+
"conducto-ai[mcp,opentelemetry,test]",
|
|
53
|
+
"mypy>=1.14",
|
|
54
|
+
"ruff>=0.9",
|
|
55
|
+
"types-protobuf==7.35.1.20260906",
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
[tool.ruff]
|
|
59
|
+
line-length = 100
|
|
60
|
+
target-version = "py312"
|
|
61
|
+
src = ["src", "tests"]
|
|
62
|
+
extend-exclude = ["*.md"]
|
|
63
|
+
|
|
64
|
+
[tool.ruff.lint]
|
|
65
|
+
select = ["E", "F", "I", "UP", "B"]
|
|
66
|
+
ignore = ["UP040", "UP047"]
|
|
67
|
+
|
|
68
|
+
[tool.ruff.lint.pydocstyle]
|
|
69
|
+
convention = "google"
|
|
70
|
+
|
|
71
|
+
[tool.mypy]
|
|
72
|
+
python_version = "3.12"
|
|
73
|
+
packages = ["conducto"]
|
|
74
|
+
mypy_path = "src"
|
|
75
|
+
strict = true
|
|
76
|
+
warn_unused_ignores = true
|
|
77
|
+
|
|
78
|
+
[tool.pytest.ini_options]
|
|
79
|
+
testpaths = ["tests"]
|
|
80
|
+
markers = [
|
|
81
|
+
"acceptance: Milestone 1 quick-start acceptance flow (stable aggregate check).",
|
|
82
|
+
"golden: Schema/golden-fixture tests pinning public wire contracts.",
|
|
83
|
+
"ollama: Opt-in tests against an already running local Ollama daemon.",
|
|
84
|
+
"vllm: Opt-in tests against an already running local vLLM OpenAI-compatible server.",
|
|
85
|
+
"lm_studio: Opt-in tests against an already running local LM Studio OpenAI-compatible server.",
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
[tool.uv.sources]
|
|
89
|
+
conducto-ai = { workspace = true }
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Application-facing entry points for the pre-v1 Conducto SDK.
|
|
2
|
+
|
|
3
|
+
Import specialized contracts from their owning ``conducto.core`` packages,
|
|
4
|
+
adapters from ``conducto.providers``, and deterministic fakes from
|
|
5
|
+
``conducto.testing``. Importing Conducto does not configure clients or logging.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .core.agent import BaseAgent
|
|
9
|
+
from .core.decorators import a2a_agent, a2a_capability, tool
|
|
10
|
+
from .core.model_config import (
|
|
11
|
+
AgentModelConfig,
|
|
12
|
+
ModelReference,
|
|
13
|
+
ModelRequirement,
|
|
14
|
+
RunConfig,
|
|
15
|
+
RuntimeConfig,
|
|
16
|
+
)
|
|
17
|
+
from .core.orchestrator import OrchestratorAgent
|
|
18
|
+
from .core.registry import AgentRegistry
|
|
19
|
+
from .core.run_context import RunContext, get_run_context, require_run_context
|
|
20
|
+
from .core.runtime import Runtime
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"AgentModelConfig",
|
|
24
|
+
"AgentRegistry",
|
|
25
|
+
"BaseAgent",
|
|
26
|
+
"ModelReference",
|
|
27
|
+
"ModelRequirement",
|
|
28
|
+
"OrchestratorAgent",
|
|
29
|
+
"RunConfig",
|
|
30
|
+
"RunContext",
|
|
31
|
+
"Runtime",
|
|
32
|
+
"RuntimeConfig",
|
|
33
|
+
"a2a_agent",
|
|
34
|
+
"a2a_capability",
|
|
35
|
+
"get_run_context",
|
|
36
|
+
"require_run_context",
|
|
37
|
+
"tool",
|
|
38
|
+
]
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""Public A2A 1.0 contracts and Conducto result mapping helpers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
|
|
7
|
+
from a2a.types.a2a_pb2 import Artifact, Part, Task, TaskState
|
|
8
|
+
from google.protobuf.struct_pb2 import Struct
|
|
9
|
+
|
|
10
|
+
from conducto.core.a2a_profile import (
|
|
11
|
+
A2A_JSONRPC_BINDING,
|
|
12
|
+
A2A_NORMATIVE_COMMIT,
|
|
13
|
+
A2A_NORMATIVE_PROTO_SHA256,
|
|
14
|
+
A2A_NORMATIVE_SOURCE,
|
|
15
|
+
A2A_NORMATIVE_TAG,
|
|
16
|
+
A2A_PROTOCOL_RELEASE,
|
|
17
|
+
A2A_PROTOCOL_VERSION,
|
|
18
|
+
A2A_PYTHON_SDK_PACKAGE,
|
|
19
|
+
A2A_PYTHON_SDK_VERSION,
|
|
20
|
+
CONDUCTO_PARAMETER_EXTENSION_URI,
|
|
21
|
+
MAX_ARTIFACT_PARTS,
|
|
22
|
+
MAX_HISTORY_MESSAGES,
|
|
23
|
+
MAX_MESSAGE_PARTS,
|
|
24
|
+
MAX_METADATA_BYTES,
|
|
25
|
+
MAX_TASK_ARTIFACTS,
|
|
26
|
+
SUPPORTED_JSONRPC_METHODS,
|
|
27
|
+
SUPPORTED_MEDIA_TYPES,
|
|
28
|
+
SUPPORTED_REQUIRED_EXTENSIONS,
|
|
29
|
+
TERMINAL_TASK_STATES,
|
|
30
|
+
A2AProtocolError,
|
|
31
|
+
parse_agent_card,
|
|
32
|
+
parse_message,
|
|
33
|
+
parse_task,
|
|
34
|
+
validate_jsonrpc_method,
|
|
35
|
+
validate_task_transition,
|
|
36
|
+
)
|
|
37
|
+
from conducto.core.invocation_results import (
|
|
38
|
+
InvocationApprovalRequired,
|
|
39
|
+
InvocationCancelled,
|
|
40
|
+
InvocationFailure,
|
|
41
|
+
InvocationResult,
|
|
42
|
+
InvocationSuccess,
|
|
43
|
+
InvocationTimeout,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def invocation_result_to_task(result: InvocationResult, *, task_id: str, context_id: str) -> Task:
|
|
48
|
+
"""Map a completed local invocation to a sanitized terminal A2A task.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
result: Outcome returned by the shared Conducto invocation pipeline.
|
|
52
|
+
task_id: Server-owned A2A task identifier.
|
|
53
|
+
context_id: A2A context identifier shared by follow-up work.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
A terminal A2A task with no local exception details.
|
|
57
|
+
"""
|
|
58
|
+
task = Task(id=task_id, context_id=context_id)
|
|
59
|
+
state = TaskState.TASK_STATE_FAILED
|
|
60
|
+
metadata: dict[str, str] = {}
|
|
61
|
+
if isinstance(result, InvocationSuccess):
|
|
62
|
+
state = TaskState.TASK_STATE_COMPLETED
|
|
63
|
+
task.artifacts.append(
|
|
64
|
+
Artifact(
|
|
65
|
+
artifact_id=f"{task_id}-result",
|
|
66
|
+
name="result",
|
|
67
|
+
parts=[Part(text=json.dumps(result.value, ensure_ascii=True, sort_keys=True))],
|
|
68
|
+
)
|
|
69
|
+
)
|
|
70
|
+
elif isinstance(result, InvocationCancelled):
|
|
71
|
+
state = TaskState.TASK_STATE_CANCELED
|
|
72
|
+
elif isinstance(result, InvocationTimeout):
|
|
73
|
+
metadata["reason"] = "timeout"
|
|
74
|
+
elif isinstance(result, InvocationApprovalRequired):
|
|
75
|
+
state = TaskState.TASK_STATE_INPUT_REQUIRED
|
|
76
|
+
metadata["reason"] = "approval_required"
|
|
77
|
+
elif isinstance(result, InvocationFailure):
|
|
78
|
+
metadata["reason"] = "capability_failure"
|
|
79
|
+
else:
|
|
80
|
+
metadata["reason"] = type(result).__name__
|
|
81
|
+
task.status.state = state
|
|
82
|
+
if metadata:
|
|
83
|
+
task.metadata.CopyFrom(Struct())
|
|
84
|
+
task.metadata.update(metadata)
|
|
85
|
+
return task
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
__all__ = [
|
|
89
|
+
"A2A_JSONRPC_BINDING",
|
|
90
|
+
"A2A_NORMATIVE_COMMIT",
|
|
91
|
+
"A2A_NORMATIVE_PROTO_SHA256",
|
|
92
|
+
"A2A_NORMATIVE_SOURCE",
|
|
93
|
+
"A2A_NORMATIVE_TAG",
|
|
94
|
+
"A2A_PROTOCOL_RELEASE",
|
|
95
|
+
"A2A_PROTOCOL_VERSION",
|
|
96
|
+
"A2A_PYTHON_SDK_PACKAGE",
|
|
97
|
+
"A2A_PYTHON_SDK_VERSION",
|
|
98
|
+
"A2AProtocolError",
|
|
99
|
+
"CONDUCTO_PARAMETER_EXTENSION_URI",
|
|
100
|
+
"invocation_result_to_task",
|
|
101
|
+
"MAX_ARTIFACT_PARTS",
|
|
102
|
+
"MAX_HISTORY_MESSAGES",
|
|
103
|
+
"MAX_MESSAGE_PARTS",
|
|
104
|
+
"MAX_METADATA_BYTES",
|
|
105
|
+
"MAX_TASK_ARTIFACTS",
|
|
106
|
+
"SUPPORTED_JSONRPC_METHODS",
|
|
107
|
+
"SUPPORTED_MEDIA_TYPES",
|
|
108
|
+
"SUPPORTED_REQUIRED_EXTENSIONS",
|
|
109
|
+
"TERMINAL_TASK_STATES",
|
|
110
|
+
"parse_agent_card",
|
|
111
|
+
"parse_message",
|
|
112
|
+
"parse_task",
|
|
113
|
+
"validate_jsonrpc_method",
|
|
114
|
+
"validate_task_transition",
|
|
115
|
+
]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Metadata-only catalog for first-party optional provider adapters.
|
|
2
|
+
|
|
3
|
+
Importing this package never imports a provider SDK, resolves credentials,
|
|
4
|
+
constructs a client, performs network I/O, or mutates the environment.
|
|
5
|
+
Concrete adapters are selected only by trusted application code and are
|
|
6
|
+
introduced independently of the core runtime.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .catalog import (
|
|
10
|
+
AdapterDependencyError,
|
|
11
|
+
AdapterSpec,
|
|
12
|
+
DiscoveredExternalAdapter,
|
|
13
|
+
ExternalAdapterSpec,
|
|
14
|
+
available_adapter_specs,
|
|
15
|
+
discover_external_adapters,
|
|
16
|
+
load_external_adapter,
|
|
17
|
+
require_adapter,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"AdapterDependencyError",
|
|
22
|
+
"AdapterSpec",
|
|
23
|
+
"DiscoveredExternalAdapter",
|
|
24
|
+
"ExternalAdapterSpec",
|
|
25
|
+
"available_adapter_specs",
|
|
26
|
+
"discover_external_adapters",
|
|
27
|
+
"load_external_adapter",
|
|
28
|
+
"require_adapter",
|
|
29
|
+
]
|