andon-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.
- andon_ai-0.1.0/.gitignore +50 -0
- andon_ai-0.1.0/AGENTS.md +1 -0
- andon_ai-0.1.0/CLAUDE.md +122 -0
- andon_ai-0.1.0/PKG-INFO +244 -0
- andon_ai-0.1.0/README.md +233 -0
- andon_ai-0.1.0/andon_cli/__init__.py +7 -0
- andon_ai-0.1.0/andon_cli/__main__.py +5 -0
- andon_ai-0.1.0/andon_cli/api.py +167 -0
- andon_ai-0.1.0/andon_cli/input_files.py +219 -0
- andon_ai-0.1.0/andon_cli/main.py +900 -0
- andon_ai-0.1.0/andon_cli/workspace.py +122 -0
- andon_ai-0.1.0/andon_dsl/__init__.py +15 -0
- andon_ai-0.1.0/andon_dsl/_graph/__init__.py +57 -0
- andon_ai-0.1.0/andon_dsl/_graph/model.py +823 -0
- andon_ai-0.1.0/andon_dsl/_identity.py +17 -0
- andon_ai-0.1.0/andon_dsl/agents/__init__.py +35 -0
- andon_ai-0.1.0/andon_dsl/agents/context.py +257 -0
- andon_ai-0.1.0/andon_dsl/agents/core.py +312 -0
- andon_ai-0.1.0/andon_dsl/agents/settings.py +64 -0
- andon_ai-0.1.0/andon_dsl/agents/templates.py +29 -0
- andon_ai-0.1.0/andon_dsl/authoring.py +29 -0
- andon_ai-0.1.0/andon_dsl/docs/__init__.py +16 -0
- andon_ai-0.1.0/andon_dsl/docs/authoring.md +350 -0
- andon_ai-0.1.0/andon_dsl/errors.py +52 -0
- andon_ai-0.1.0/andon_dsl/integrations/__init__.py +31 -0
- andon_ai-0.1.0/andon_dsl/integrations/connections.py +278 -0
- andon_ai-0.1.0/andon_dsl/resources/__init__.py +32 -0
- andon_ai-0.1.0/andon_dsl/resources/artifacts.py +300 -0
- andon_ai-0.1.0/andon_dsl/resources/documents.py +32 -0
- andon_ai-0.1.0/andon_dsl/resources/files.py +181 -0
- andon_ai-0.1.0/andon_dsl/resources/reference_data.py +101 -0
- andon_ai-0.1.0/andon_dsl/resources/schema.py +11 -0
- andon_ai-0.1.0/andon_dsl/tools/__init__.py +35 -0
- andon_ai-0.1.0/andon_dsl/tools/catalog.py +110 -0
- andon_ai-0.1.0/andon_dsl/tools/core.py +134 -0
- andon_ai-0.1.0/andon_dsl/tools/stubs.py +209 -0
- andon_ai-0.1.0/andon_dsl/tools/toolsets.py +72 -0
- andon_ai-0.1.0/andon_dsl/tools/web.py +21 -0
- andon_ai-0.1.0/andon_dsl/validation/__init__.py +47 -0
- andon_ai-0.1.0/andon_dsl/validation/rules.py +6026 -0
- andon_ai-0.1.0/andon_dsl/workflows/__init__.py +40 -0
- andon_ai-0.1.0/andon_dsl/workflows/core.py +361 -0
- andon_ai-0.1.0/andon_dsl/workflows/durations.py +37 -0
- andon_ai-0.1.0/andon_dsl/workflows/primitives.py +647 -0
- andon_ai-0.1.0/andon_dsl/workflows/steps.py +353 -0
- andon_ai-0.1.0/andon_dsl/workspace/__init__.py +17 -0
- andon_ai-0.1.0/andon_dsl/workspace/template.py +265 -0
- andon_ai-0.1.0/pyproject.toml +41 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
.venv/
|
|
8
|
+
|
|
9
|
+
# Environment
|
|
10
|
+
.env
|
|
11
|
+
.env.*
|
|
12
|
+
|
|
13
|
+
# IDE
|
|
14
|
+
.vscode/*
|
|
15
|
+
!.vscode/settings.json
|
|
16
|
+
.idea/
|
|
17
|
+
.claude/
|
|
18
|
+
|
|
19
|
+
# OS
|
|
20
|
+
.DS_Store
|
|
21
|
+
|
|
22
|
+
# Testing
|
|
23
|
+
.pytest_cache/
|
|
24
|
+
.coverage
|
|
25
|
+
htmlcov/
|
|
26
|
+
|
|
27
|
+
# Node (frontend)
|
|
28
|
+
node_modules/
|
|
29
|
+
web/dist/
|
|
30
|
+
|
|
31
|
+
# Local storage data dirs for LocalFileService / LocalGitStore. Path
|
|
32
|
+
# depends on cwd: ``./storage`` from project root, ``./storage`` from
|
|
33
|
+
# backend/. Anchor each so we don't accidentally ignore Python
|
|
34
|
+
# packages named ``storage`` (e.g. ``backend/src/connections/storage/``
|
|
35
|
+
# for the S3 provider).
|
|
36
|
+
/storage/
|
|
37
|
+
/backend/storage/
|
|
38
|
+
|
|
39
|
+
# Logfire
|
|
40
|
+
.logfire/
|
|
41
|
+
|
|
42
|
+
# Large test assets (downloaded on demand)
|
|
43
|
+
backend/tests/assets/nvda-*
|
|
44
|
+
|
|
45
|
+
# denials triage demo patient documents are generated locally from anonymized seed data.
|
|
46
|
+
sdk/examples/denials_triage/andon/data/patient/
|
|
47
|
+
|
|
48
|
+
# Local demo run state.
|
|
49
|
+
.demo/
|
|
50
|
+
sdk/examples/denials_triage/.demo/
|
andon_ai-0.1.0/AGENTS.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
CLAUDE.md
|
andon_ai-0.1.0/CLAUDE.md
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
Andon SDK is the public authoring surface for workflows, agents, tools,
|
|
4
|
+
connections, and the CLI used to validate and deploy them.
|
|
5
|
+
|
|
6
|
+
## Documentation Ownership
|
|
7
|
+
|
|
8
|
+
- `README.md` is the release-facing introduction and tutorial. Keep its
|
|
9
|
+
examples small, executable, and limited to product capabilities offered to
|
|
10
|
+
authors.
|
|
11
|
+
- `andon_dsl/docs/authoring.md` is the exact workspace-authoring contract
|
|
12
|
+
shipped in the wheel and printed by `andon docs`. Put DSL rules, durability
|
|
13
|
+
semantics, limits, and sharp edges there.
|
|
14
|
+
- Platform tool stubs and their docstrings are the capability contract printed
|
|
15
|
+
by `andon tools`. Do not duplicate tool signatures or provider details in
|
|
16
|
+
the README or generated agent guidance.
|
|
17
|
+
- `andon_dsl/workspace/template.py` seeds the workspace `andon/AGENTS.md`. Keep
|
|
18
|
+
that guide concise and route coding agents to `andon docs` and `andon tools`
|
|
19
|
+
for version-matched contracts.
|
|
20
|
+
- `examples/` holds demo workspaces that live only in this repo; they are
|
|
21
|
+
excluded from the published package. Every example workflow must validate
|
|
22
|
+
and compile against the current SDK and be exercised by a test — fix or
|
|
23
|
+
delete an example rather than letting it drift.
|
|
24
|
+
|
|
25
|
+
## Workflow Authoring
|
|
26
|
+
|
|
27
|
+
- Keep `@workflow`, `@step`, `@tool`, and `Agent(...)` declarations at module
|
|
28
|
+
scope. Agent declarations must be direct module-level assignments like
|
|
29
|
+
`extractor = Agent(...)` so deploy-time discovery can give them stable
|
|
30
|
+
identities.
|
|
31
|
+
- Workflow bodies describe durable orchestration. Use `branch(...)`, `map(...)`,
|
|
32
|
+
`loop(...)`, `wait_for_event(...)`, and `run_workflow(...)` for control flow;
|
|
33
|
+
put normal Python branching, loops, parsing, and API glue inside `@step`
|
|
34
|
+
bodies.
|
|
35
|
+
- Agent prompt templates are Handlebars over the typed `inputs` object
|
|
36
|
+
(computed fields included): `{{claim.patient.name}}` paths, `{{#if}}` /
|
|
37
|
+
`{{#each}}` blocks, and the `{{json field}}` helper for embedding a field
|
|
38
|
+
as pretty-printed JSON. Rendering is strict (a missing path fails the
|
|
39
|
+
run). Statically known call-site templates are validated against the
|
|
40
|
+
agent's `input_type` during deploy; every rendered template is validated
|
|
41
|
+
again at dispatch. The contract lives in `andon_dsl.agents.templates`.
|
|
42
|
+
Agent calls accept the same text/image/document `Prompt` shape as
|
|
43
|
+
`ctx.prompt`; rendering applies to text parts. Do not use Python
|
|
44
|
+
`str.format` braces in agent prompts; write a literal `{{` as `\{{`.
|
|
45
|
+
- `Agent(output_type=...)` and `Agent(output_schema_field=...)` are mutually
|
|
46
|
+
exclusive. `output_schema_field` names an input field whose value is a JSON
|
|
47
|
+
Schema dict for the full agent output. `output_type` may be a union; prefer a
|
|
48
|
+
discriminated union when variants share fields.
|
|
49
|
+
- `output_validators=[fn]` functions receive `(inputs, output)` after type or
|
|
50
|
+
schema validation. Raise `AgentRetryError` when the model should repair the
|
|
51
|
+
output. Return a replacement output to normalize it, or `None` to keep the
|
|
52
|
+
current value. Ordinary exceptions, including `ValueError`, are treated as
|
|
53
|
+
validator bugs and fail the run. Validators should be deterministic in
|
|
54
|
+
`(inputs, output)` because validation may re-run against a cached model
|
|
55
|
+
response during replay.
|
|
56
|
+
- Error types mean different things: `AgentRetryError` is feedback to the model
|
|
57
|
+
for tool calls and output validators; `StepRetryError` consumes the step
|
|
58
|
+
retry budget; `UserReadableError` fails with a user-safe message; ordinary
|
|
59
|
+
exceptions are internal failures. Use a typed agent result for expected
|
|
60
|
+
recoverable outcomes; `UserReadableError` is a terminal run failure rather
|
|
61
|
+
than step-level fallback control flow.
|
|
62
|
+
- `Agent(code_mode=True)` loads typed cell inputs through `get_inputs()` and
|
|
63
|
+
finalizes through `SUBMIT(result=...)`. Injected tools are keyword-only;
|
|
64
|
+
await those rendered as `async def` in the `run_code` catalog.
|
|
65
|
+
`get_inputs()` and `SUBMIT(...)` are synchronous. A plain text answer is not
|
|
66
|
+
a final structured result. `SUBMIT` runs declared type/schema checks
|
|
67
|
+
immediately; custom output validators run after submission while the agent
|
|
68
|
+
can still retry.
|
|
69
|
+
- Deployed workflow execution validates declared output contracts in the
|
|
70
|
+
sandbox, where the original user classes and validators exist. Runtime code
|
|
71
|
+
outside the artifact may see metadata-only specs for deployed tools and
|
|
72
|
+
validators, not live Python callables.
|
|
73
|
+
|
|
74
|
+
## Tools And Files
|
|
75
|
+
|
|
76
|
+
- Use `@tool` for model-callable helpers. Tool bodies should raise
|
|
77
|
+
`AgentRetryError` only for bad model-supplied arguments the model can
|
|
78
|
+
repair (malformed input, an id the model invented). A legitimate miss
|
|
79
|
+
("no catalog entry for this code") is a result, not an error: return an
|
|
80
|
+
empty list or `None` and put "an empty result is the final answer — do
|
|
81
|
+
not retry" guidance in the docstring. Retry feedback is budgeted by
|
|
82
|
+
`Agent(retries=N)`; a raise that fires on valid data can exhaust the
|
|
83
|
+
budget and fail the run on a normal domain outcome. Rule of thumb: an
|
|
84
|
+
`AgentRetryError` should be unreachable for a well-behaved model
|
|
85
|
+
operating on valid data.
|
|
86
|
+
- Platform tools in `andon_dsl.tools` are SDK stubs; their implementations run
|
|
87
|
+
in the platform runtime. Keep user-authored workflow logic in the workflow
|
|
88
|
+
package, not in platform stubs.
|
|
89
|
+
- Give agents `web_search`/`web_fetch` for web browsing. Use
|
|
90
|
+
`fetch_to_file_ref` when an external URL must become a `FileRef` for
|
|
91
|
+
document tools or later workflow steps. Large payload spillover belongs in
|
|
92
|
+
runtime payload handling, not in web browsing stubs.
|
|
93
|
+
- Put document `FileRef` fields on the agent's typed inputs. A `FileRef`
|
|
94
|
+
renders as its `andon://...` URI in prompt templates and context blocks;
|
|
95
|
+
tell the model to pass that URI unchanged to typed tool arguments such as
|
|
96
|
+
`read_document(file=...)`. File metadata and bytes stay behind the runtime
|
|
97
|
+
reference. Keep the workflow and agent fields typed as `FileRef`; the CLI
|
|
98
|
+
accepts local paths at those schema positions and uploads them before run
|
|
99
|
+
creation.
|
|
100
|
+
- `StrategyFile(...)` paths resolve relative to the file that defines the
|
|
101
|
+
agent and must point to markdown files under `andon/prompts`.
|
|
102
|
+
|
|
103
|
+
## Validation
|
|
104
|
+
|
|
105
|
+
- Promote invariants into the SDK-time validator whenever the artifact tree
|
|
106
|
+
carries enough information to check them.
|
|
107
|
+
- Keep executable-body validation source-only. Resolve step/tool names with
|
|
108
|
+
Python lexical scoping, require workspace imports to resolve inside the
|
|
109
|
+
deployed tree, reject wildcard and platform-internal imports, and leave
|
|
110
|
+
third-party package availability to `andon.toml` `[sandbox] packages`.
|
|
111
|
+
- Workflow primitives run only in `@workflow` bodies. User-authored `@step`
|
|
112
|
+
and `@tool` contexts expose `connect`, `prompt`, artifact I/O, and document
|
|
113
|
+
reads; validate direct context-member calls against that runtime surface.
|
|
114
|
+
- Extend learning and evaluation capabilities through compile-discovered named
|
|
115
|
+
code artifacts or platform stores keyed by structured definition, call-site,
|
|
116
|
+
and execution references. Keep domain semantics such as metrics, confidence,
|
|
117
|
+
verdicts, corrections, and datasets out of workflow IR node types.
|
|
118
|
+
- Keep source coordinates on validation errors: file, module path, binding or
|
|
119
|
+
function name, and line.
|
|
120
|
+
- When a step or tool footgun recurs, constrain its body shape at validation
|
|
121
|
+
time or add an explicit DSL primitive instead of leaving it to fail in the
|
|
122
|
+
sandbox.
|
andon_ai-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: andon-ai
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Andon SDK and CLI for authoring, deploying, and running workflows
|
|
5
|
+
Requires-Python: >=3.13
|
|
6
|
+
Requires-Dist: httpx>=0.28
|
|
7
|
+
Requires-Dist: packaging>=24.0
|
|
8
|
+
Requires-Dist: pydantic>=2.0
|
|
9
|
+
Requires-Dist: typing-extensions>=4.15
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# Andon SDK and CLI (`andon-ai`)
|
|
13
|
+
|
|
14
|
+
Andon is a Python SDK for building durable, document-centric workflows with
|
|
15
|
+
typed steps, LLM agents, human review, and integrations. Authors define the
|
|
16
|
+
workflow; the Andon platform handles execution, checkpointing, files, and
|
|
17
|
+
operations.
|
|
18
|
+
|
|
19
|
+
Installing `andon-ai` provides the `andon` command and the `andon_dsl` Python
|
|
20
|
+
package. Python 3.13 or newer and [uv](https://docs.astral.sh/uv/) are required.
|
|
21
|
+
|
|
22
|
+
## Create a workspace
|
|
23
|
+
|
|
24
|
+
Start in an empty directory:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
mkdir claims-workflow
|
|
28
|
+
cd claims-workflow
|
|
29
|
+
uvx andon-ai init
|
|
30
|
+
uv sync
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`andon init` creates `andon.toml`, a deployable `andon/` package, a sample
|
|
34
|
+
workflow and test, and local project configuration. It preserves files that
|
|
35
|
+
already exist, so an empty directory is the supported starting point.
|
|
36
|
+
|
|
37
|
+
The generated `AGENTS.md` routes coding agents to the authoring contract and
|
|
38
|
+
tool catalog that match the installed SDK.
|
|
39
|
+
|
|
40
|
+
## Build an email workflow
|
|
41
|
+
|
|
42
|
+
This workflow reads unread Gmail messages, summarizes them with an agent, and
|
|
43
|
+
emails the digest. Save it as `andon/workflows/inbox.py`:
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from dataclasses import dataclass
|
|
47
|
+
|
|
48
|
+
from andon_dsl.agents import Agent, StepContext
|
|
49
|
+
from andon_dsl.integrations import EmailFilter, EmailMessage, Gmail
|
|
50
|
+
from andon_dsl.workflows import map, step, workflow
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@dataclass
|
|
54
|
+
class InboxInput:
|
|
55
|
+
recipient: str
|
|
56
|
+
limit: int = 10
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@dataclass
|
|
60
|
+
class EmailSummary:
|
|
61
|
+
sender: str
|
|
62
|
+
subject: str
|
|
63
|
+
summary: str
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
summarizer = Agent(
|
|
67
|
+
model_family="small",
|
|
68
|
+
input_type=EmailMessage,
|
|
69
|
+
output_type=EmailSummary,
|
|
70
|
+
system_instructions="Summarize inbound email clearly and concisely.",
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@step(connections=["gmail"])
|
|
75
|
+
async def read_inbox(ctx: StepContext, input: InboxInput) -> list[EmailMessage]:
|
|
76
|
+
gmail = await ctx.connect(Gmail, "gmail")
|
|
77
|
+
return await gmail.list_messages(
|
|
78
|
+
filter=EmailFilter(is_unread=True),
|
|
79
|
+
limit=input.limit,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@step
|
|
84
|
+
async def summarize(message: EmailMessage) -> EmailSummary:
|
|
85
|
+
return await summarizer(
|
|
86
|
+
"Summarize this email from {{sender}}.\n"
|
|
87
|
+
"Subject: {{subject}}\n\n"
|
|
88
|
+
"{{body_text}}",
|
|
89
|
+
inputs=message,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@step(connections=["gmail"])
|
|
94
|
+
async def send_digest(
|
|
95
|
+
ctx: StepContext,
|
|
96
|
+
recipient: str,
|
|
97
|
+
summaries: list[EmailSummary],
|
|
98
|
+
) -> str:
|
|
99
|
+
gmail = await ctx.connect(Gmail, "gmail")
|
|
100
|
+
body = "\n\n".join(
|
|
101
|
+
f"{item.subject} — {item.sender}\n{item.summary}" for item in summaries
|
|
102
|
+
)
|
|
103
|
+
return await gmail.send(
|
|
104
|
+
to=[recipient],
|
|
105
|
+
subject="Andon inbox digest",
|
|
106
|
+
body=body or "No unread messages.",
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@workflow()
|
|
111
|
+
def process_inbox(input: InboxInput) -> str:
|
|
112
|
+
messages = read_inbox(input)
|
|
113
|
+
summaries = map(summarize, messages)
|
|
114
|
+
return send_digest(input.recipient, summaries)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Declare the workflow in `andon.toml`:
|
|
118
|
+
|
|
119
|
+
```toml
|
|
120
|
+
[[workflows]]
|
|
121
|
+
name = "process_inbox"
|
|
122
|
+
path = "andon/workflows/inbox.py"
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
The connection name passed to `ctx.connect()` refers to Gmail credentials
|
|
126
|
+
configured for the current Andon organization. The same name must appear in
|
|
127
|
+
the step's `connections=[...]` allow-list.
|
|
128
|
+
|
|
129
|
+
## Core concepts
|
|
130
|
+
|
|
131
|
+
- **Workflows** are declarative graphs of steps and control-flow primitives.
|
|
132
|
+
Their bodies are traced during deployment and do not run as ordinary Python
|
|
133
|
+
during workflow execution.
|
|
134
|
+
- **Steps** are typed Python functions and the durability boundary. Successful
|
|
135
|
+
results are checkpointed; external side effects should be safe to repeat if
|
|
136
|
+
an interrupted attempt runs again.
|
|
137
|
+
- **Agents** are typed LLM-powered components declared at module scope and
|
|
138
|
+
awaited inside steps. Runtime prompts are Handlebars templates over the
|
|
139
|
+
agent's typed inputs.
|
|
140
|
+
- **Tools and toolsets** give agents explicitly selected capabilities. Andon
|
|
141
|
+
provides platform tools and curated toolsets, and authors can define their
|
|
142
|
+
own model-callable functions with `@tool`.
|
|
143
|
+
- **Connections** provide typed access to organization-configured email through
|
|
144
|
+
the Gmail protocol without exposing credentials to workflow code.
|
|
145
|
+
- **FileRef** values represent uploaded files and generated artifacts. Keep
|
|
146
|
+
documents and large intermediate outputs behind `FileRef` rather than
|
|
147
|
+
passing their bytes or full text through step results.
|
|
148
|
+
|
|
149
|
+
Workflow bodies use primitives such as `map`, `parallel`, `branch`, `loop`,
|
|
150
|
+
`wait_for_event`, `wait_for_review`, `sleep`, and `run_workflow`. Put ordinary
|
|
151
|
+
Python branching, iteration, parsing, and integration glue inside steps.
|
|
152
|
+
|
|
153
|
+
## Tools and toolsets
|
|
154
|
+
|
|
155
|
+
Platform tools and curated toolsets are imported from `andon_dsl.tools` and
|
|
156
|
+
opted into an agent through `tools=[...]`. Authors can combine them with their
|
|
157
|
+
own `@tool` functions:
|
|
158
|
+
|
|
159
|
+
```python
|
|
160
|
+
from andon_dsl.agents import Agent
|
|
161
|
+
from andon_dsl.tools import tool
|
|
162
|
+
from andon_dsl.tools.toolsets import document_analysis
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
@tool
|
|
166
|
+
def normalize_vendor_name(name: str) -> str:
|
|
167
|
+
"""Return a normalized vendor name for matching."""
|
|
168
|
+
return " ".join(name.lower().split())
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
analyst = Agent(
|
|
172
|
+
tools=[*document_analysis.tools, normalize_vendor_name],
|
|
173
|
+
)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
The installed SDK is the source of truth for platform capabilities:
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
uv run andon tools # print tools, toolsets, signatures, and descriptions
|
|
180
|
+
uv run andon tools --json # emit the same catalog as structured JSON
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Validate, deploy, and run
|
|
184
|
+
|
|
185
|
+
An organization admin creates API keys in the console's
|
|
186
|
+
[Settings page](https://app.andonai.com/settings). Keys carry a role:
|
|
187
|
+
`admin` keys can deploy and activate; `operator` keys can start and watch
|
|
188
|
+
runs. Expose the key to the CLI:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
export ANDON_API_KEY="ak-..."
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
The CLI uses `https://app.andonai.com/` by default. Set `ANDON_API_URL` only
|
|
195
|
+
when targeting a different Andon environment.
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
uv run andon validate
|
|
199
|
+
uv run pytest
|
|
200
|
+
uv run andon deploy --no-activate
|
|
201
|
+
uv run andon run process_inbox \
|
|
202
|
+
--deployment-id <deployment-id> \
|
|
203
|
+
--input-json '{"recipient":"ops@example.com","limit":10}'
|
|
204
|
+
uv run andon runs watch <run-id>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
`andon validate` performs local manifest and static source validation.
|
|
208
|
+
`andon deploy` publishes the full local `andon.toml` plus `andon/` snapshot,
|
|
209
|
+
compiles and type-checks its workflows, and activates the deployment unless
|
|
210
|
+
`--no-activate` is passed. Publishing replaces the remote workspace snapshot,
|
|
211
|
+
so remote files absent from the local tree are deleted.
|
|
212
|
+
|
|
213
|
+
`andon run` starts a deployed workflow. Local paths supplied at typed
|
|
214
|
+
`FileRef` input positions are uploaded before run creation.
|
|
215
|
+
|
|
216
|
+
## Authoring reference
|
|
217
|
+
|
|
218
|
+
Use the references bundled with the installed SDK before editing a workspace:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
uv run andon docs
|
|
222
|
+
uv run andon tools
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Here `uv run` executes a command in the workspace environment, while
|
|
226
|
+
`andon docs` prints the complete, version-matched authoring contract to the
|
|
227
|
+
terminal. It is separate from `andon run <workflow>`, which starts a workflow
|
|
228
|
+
run.
|
|
229
|
+
|
|
230
|
+
The authoring contract covers workflow restrictions, primitives, durable
|
|
231
|
+
identity, retries, agent settings, files, reference data, testing, and other
|
|
232
|
+
sharp edges. The generated `andon/AGENTS.md` points coding agents to this
|
|
233
|
+
contract and the installed tool catalog.
|
|
234
|
+
|
|
235
|
+
## Public imports
|
|
236
|
+
|
|
237
|
+
| Package | Purpose |
|
|
238
|
+
|---|---|
|
|
239
|
+
| `andon_dsl.workflows` | Workflow and step decorators plus control-flow primitives. |
|
|
240
|
+
| `andon_dsl.agents` | Agent declarations, prompt content, contexts, model settings, and usage limits. |
|
|
241
|
+
| `andon_dsl.tools` | User-authored tools and platform tool stubs; curated bundles live in `andon_dsl.tools.toolsets`. |
|
|
242
|
+
| `andon_dsl.resources` | `FileRef`, document result types, reference data helpers, and schema extensions. |
|
|
243
|
+
| `andon_dsl.integrations` | The Gmail connection protocol and shared email types for `ctx.connect()`. |
|
|
244
|
+
| `andon_dsl.errors` | Public authoring and execution error types. |
|
andon_ai-0.1.0/README.md
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# Andon SDK and CLI (`andon-ai`)
|
|
2
|
+
|
|
3
|
+
Andon is a Python SDK for building durable, document-centric workflows with
|
|
4
|
+
typed steps, LLM agents, human review, and integrations. Authors define the
|
|
5
|
+
workflow; the Andon platform handles execution, checkpointing, files, and
|
|
6
|
+
operations.
|
|
7
|
+
|
|
8
|
+
Installing `andon-ai` provides the `andon` command and the `andon_dsl` Python
|
|
9
|
+
package. Python 3.13 or newer and [uv](https://docs.astral.sh/uv/) are required.
|
|
10
|
+
|
|
11
|
+
## Create a workspace
|
|
12
|
+
|
|
13
|
+
Start in an empty directory:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
mkdir claims-workflow
|
|
17
|
+
cd claims-workflow
|
|
18
|
+
uvx andon-ai init
|
|
19
|
+
uv sync
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`andon init` creates `andon.toml`, a deployable `andon/` package, a sample
|
|
23
|
+
workflow and test, and local project configuration. It preserves files that
|
|
24
|
+
already exist, so an empty directory is the supported starting point.
|
|
25
|
+
|
|
26
|
+
The generated `AGENTS.md` routes coding agents to the authoring contract and
|
|
27
|
+
tool catalog that match the installed SDK.
|
|
28
|
+
|
|
29
|
+
## Build an email workflow
|
|
30
|
+
|
|
31
|
+
This workflow reads unread Gmail messages, summarizes them with an agent, and
|
|
32
|
+
emails the digest. Save it as `andon/workflows/inbox.py`:
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from dataclasses import dataclass
|
|
36
|
+
|
|
37
|
+
from andon_dsl.agents import Agent, StepContext
|
|
38
|
+
from andon_dsl.integrations import EmailFilter, EmailMessage, Gmail
|
|
39
|
+
from andon_dsl.workflows import map, step, workflow
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass
|
|
43
|
+
class InboxInput:
|
|
44
|
+
recipient: str
|
|
45
|
+
limit: int = 10
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass
|
|
49
|
+
class EmailSummary:
|
|
50
|
+
sender: str
|
|
51
|
+
subject: str
|
|
52
|
+
summary: str
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
summarizer = Agent(
|
|
56
|
+
model_family="small",
|
|
57
|
+
input_type=EmailMessage,
|
|
58
|
+
output_type=EmailSummary,
|
|
59
|
+
system_instructions="Summarize inbound email clearly and concisely.",
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@step(connections=["gmail"])
|
|
64
|
+
async def read_inbox(ctx: StepContext, input: InboxInput) -> list[EmailMessage]:
|
|
65
|
+
gmail = await ctx.connect(Gmail, "gmail")
|
|
66
|
+
return await gmail.list_messages(
|
|
67
|
+
filter=EmailFilter(is_unread=True),
|
|
68
|
+
limit=input.limit,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@step
|
|
73
|
+
async def summarize(message: EmailMessage) -> EmailSummary:
|
|
74
|
+
return await summarizer(
|
|
75
|
+
"Summarize this email from {{sender}}.\n"
|
|
76
|
+
"Subject: {{subject}}\n\n"
|
|
77
|
+
"{{body_text}}",
|
|
78
|
+
inputs=message,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@step(connections=["gmail"])
|
|
83
|
+
async def send_digest(
|
|
84
|
+
ctx: StepContext,
|
|
85
|
+
recipient: str,
|
|
86
|
+
summaries: list[EmailSummary],
|
|
87
|
+
) -> str:
|
|
88
|
+
gmail = await ctx.connect(Gmail, "gmail")
|
|
89
|
+
body = "\n\n".join(
|
|
90
|
+
f"{item.subject} — {item.sender}\n{item.summary}" for item in summaries
|
|
91
|
+
)
|
|
92
|
+
return await gmail.send(
|
|
93
|
+
to=[recipient],
|
|
94
|
+
subject="Andon inbox digest",
|
|
95
|
+
body=body or "No unread messages.",
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@workflow()
|
|
100
|
+
def process_inbox(input: InboxInput) -> str:
|
|
101
|
+
messages = read_inbox(input)
|
|
102
|
+
summaries = map(summarize, messages)
|
|
103
|
+
return send_digest(input.recipient, summaries)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Declare the workflow in `andon.toml`:
|
|
107
|
+
|
|
108
|
+
```toml
|
|
109
|
+
[[workflows]]
|
|
110
|
+
name = "process_inbox"
|
|
111
|
+
path = "andon/workflows/inbox.py"
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The connection name passed to `ctx.connect()` refers to Gmail credentials
|
|
115
|
+
configured for the current Andon organization. The same name must appear in
|
|
116
|
+
the step's `connections=[...]` allow-list.
|
|
117
|
+
|
|
118
|
+
## Core concepts
|
|
119
|
+
|
|
120
|
+
- **Workflows** are declarative graphs of steps and control-flow primitives.
|
|
121
|
+
Their bodies are traced during deployment and do not run as ordinary Python
|
|
122
|
+
during workflow execution.
|
|
123
|
+
- **Steps** are typed Python functions and the durability boundary. Successful
|
|
124
|
+
results are checkpointed; external side effects should be safe to repeat if
|
|
125
|
+
an interrupted attempt runs again.
|
|
126
|
+
- **Agents** are typed LLM-powered components declared at module scope and
|
|
127
|
+
awaited inside steps. Runtime prompts are Handlebars templates over the
|
|
128
|
+
agent's typed inputs.
|
|
129
|
+
- **Tools and toolsets** give agents explicitly selected capabilities. Andon
|
|
130
|
+
provides platform tools and curated toolsets, and authors can define their
|
|
131
|
+
own model-callable functions with `@tool`.
|
|
132
|
+
- **Connections** provide typed access to organization-configured email through
|
|
133
|
+
the Gmail protocol without exposing credentials to workflow code.
|
|
134
|
+
- **FileRef** values represent uploaded files and generated artifacts. Keep
|
|
135
|
+
documents and large intermediate outputs behind `FileRef` rather than
|
|
136
|
+
passing their bytes or full text through step results.
|
|
137
|
+
|
|
138
|
+
Workflow bodies use primitives such as `map`, `parallel`, `branch`, `loop`,
|
|
139
|
+
`wait_for_event`, `wait_for_review`, `sleep`, and `run_workflow`. Put ordinary
|
|
140
|
+
Python branching, iteration, parsing, and integration glue inside steps.
|
|
141
|
+
|
|
142
|
+
## Tools and toolsets
|
|
143
|
+
|
|
144
|
+
Platform tools and curated toolsets are imported from `andon_dsl.tools` and
|
|
145
|
+
opted into an agent through `tools=[...]`. Authors can combine them with their
|
|
146
|
+
own `@tool` functions:
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
from andon_dsl.agents import Agent
|
|
150
|
+
from andon_dsl.tools import tool
|
|
151
|
+
from andon_dsl.tools.toolsets import document_analysis
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
@tool
|
|
155
|
+
def normalize_vendor_name(name: str) -> str:
|
|
156
|
+
"""Return a normalized vendor name for matching."""
|
|
157
|
+
return " ".join(name.lower().split())
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
analyst = Agent(
|
|
161
|
+
tools=[*document_analysis.tools, normalize_vendor_name],
|
|
162
|
+
)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
The installed SDK is the source of truth for platform capabilities:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
uv run andon tools # print tools, toolsets, signatures, and descriptions
|
|
169
|
+
uv run andon tools --json # emit the same catalog as structured JSON
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Validate, deploy, and run
|
|
173
|
+
|
|
174
|
+
An organization admin creates API keys in the console's
|
|
175
|
+
[Settings page](https://app.andonai.com/settings). Keys carry a role:
|
|
176
|
+
`admin` keys can deploy and activate; `operator` keys can start and watch
|
|
177
|
+
runs. Expose the key to the CLI:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
export ANDON_API_KEY="ak-..."
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
The CLI uses `https://app.andonai.com/` by default. Set `ANDON_API_URL` only
|
|
184
|
+
when targeting a different Andon environment.
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
uv run andon validate
|
|
188
|
+
uv run pytest
|
|
189
|
+
uv run andon deploy --no-activate
|
|
190
|
+
uv run andon run process_inbox \
|
|
191
|
+
--deployment-id <deployment-id> \
|
|
192
|
+
--input-json '{"recipient":"ops@example.com","limit":10}'
|
|
193
|
+
uv run andon runs watch <run-id>
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
`andon validate` performs local manifest and static source validation.
|
|
197
|
+
`andon deploy` publishes the full local `andon.toml` plus `andon/` snapshot,
|
|
198
|
+
compiles and type-checks its workflows, and activates the deployment unless
|
|
199
|
+
`--no-activate` is passed. Publishing replaces the remote workspace snapshot,
|
|
200
|
+
so remote files absent from the local tree are deleted.
|
|
201
|
+
|
|
202
|
+
`andon run` starts a deployed workflow. Local paths supplied at typed
|
|
203
|
+
`FileRef` input positions are uploaded before run creation.
|
|
204
|
+
|
|
205
|
+
## Authoring reference
|
|
206
|
+
|
|
207
|
+
Use the references bundled with the installed SDK before editing a workspace:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
uv run andon docs
|
|
211
|
+
uv run andon tools
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Here `uv run` executes a command in the workspace environment, while
|
|
215
|
+
`andon docs` prints the complete, version-matched authoring contract to the
|
|
216
|
+
terminal. It is separate from `andon run <workflow>`, which starts a workflow
|
|
217
|
+
run.
|
|
218
|
+
|
|
219
|
+
The authoring contract covers workflow restrictions, primitives, durable
|
|
220
|
+
identity, retries, agent settings, files, reference data, testing, and other
|
|
221
|
+
sharp edges. The generated `andon/AGENTS.md` points coding agents to this
|
|
222
|
+
contract and the installed tool catalog.
|
|
223
|
+
|
|
224
|
+
## Public imports
|
|
225
|
+
|
|
226
|
+
| Package | Purpose |
|
|
227
|
+
|---|---|
|
|
228
|
+
| `andon_dsl.workflows` | Workflow and step decorators plus control-flow primitives. |
|
|
229
|
+
| `andon_dsl.agents` | Agent declarations, prompt content, contexts, model settings, and usage limits. |
|
|
230
|
+
| `andon_dsl.tools` | User-authored tools and platform tool stubs; curated bundles live in `andon_dsl.tools.toolsets`. |
|
|
231
|
+
| `andon_dsl.resources` | `FileRef`, document result types, reference data helpers, and schema extensions. |
|
|
232
|
+
| `andon_dsl.integrations` | The Gmail connection protocol and shared email types for `ctx.connect()`. |
|
|
233
|
+
| `andon_dsl.errors` | Public authoring and execution error types. |
|