# Assisted Action Authoring (/docs/connectors/assisted-authoring)



Assisted Authoring is a just-in-time workbench for building a single **connector
function** with an agent in the loop. Where [Building a Provider](/docs/connectors/building-a-provider)
documents the *manual* paths — declarative `ProviderSpec` manifests and
hand-written Go — this is the *assisted* alternative: an agent proposes function
source, Ductor compiles and dry-runs it through governed runtimes, and every
iteration is recorded as auditable lineage. Nothing here bypasses the same
certification, promotion, artifact-graph, and rollout-evidence gates that manual
providers pass through; it only front-loads the write-and-verify loop.

All endpoints live under `/api/connectors/authoring` and are tenant- and
environment-scoped.

<Callout type="info">
  Assisted Authoring produces a **deployment proposal**, not a live connector. The
  proposal still has to be promoted through your normal operations workspace and
  rollout gates before it serves traffic.
</Callout>

## When to use it [#when-to-use-it]

Use assisted authoring when you need a single connector function and can describe
the intended provider, integration, function name, function kind, and
environment before the work starts. It is the no-code/operator path for the same
connector lifecycle documented in [Building a Provider](/docs/connectors/building-a-provider):
the agent helps draft source, while Ductor compiles, dry-runs, records repairs,
evaluates readiness, and produces a staged proposal.

The outcome is deliberately narrow: a ready proposal attached to the operations
workspace. It does not create a live connection, skip certification, activate an
integration deployment, or bypass the marketplace and rollout evidence gates.

## What you provide [#what-you-provide]

The operator supplies the session scope (`provider_key`, `integration_key`,
`function_name`, `function_kind`, and `environment_id`) and an intent that is
specific enough for the agent to draft the function. Each source draft then
records provenance and a hash-bound redacted source reference, so subsequent
compile, dry-run, repair, and readiness records can be replayed as one lineage.

## Review before proposal [#review-before-proposal]

Before creating a proposal, review the same surfaces readiness evaluates:

* Setup readiness, permissions, entitlements, mutation semantics, field catalog,
  secret references, certification, promotion, artifact graph, and rollout
  evidence have no blockers.
* Dry-runs used sandbox, fixture, or other non-production inputs unless
  `allows_production_data` was deliberately permitted.
* Failed compile or dry-run attempts are linked to repairs with a reason, rather
  than replaced by disconnected drafts.
* The action's write behavior matches the semantics expected by connector
  certification and deployment promotion.
* Any connection or credential work stays in the connector connection lifecycle;
  the authoring session never exposes stored credentials.

## The loop [#the-loop]

A session walks a draft from intent to a staged proposal. The compile → dry-run
→ repair cycle repeats until readiness evaluates clean.

```mermaid
flowchart TD
  A[Create session] --> B[Set intent]
  B --> C[Submit source draft]
  C --> D[Compile attempt]
  D -->|fail| R[Record repair]
  D -->|ok| E[Dry-run attempt]
  E -->|fail| R
  R --> C
  E -->|ok| F[Evaluate readiness]
  F -->|blockers| R
  F -->|allowed| G[Create proposal]
  G --> H[Attach to workspace]
  H --> I[Timeline / audit]
```

## Endpoints [#endpoints]

<TypeTable
  type="{
  &#x22;POST /sessions&#x22;: { description: &#x22;Create a tenant/environment-scoped authoring session.&#x22; },
  &#x22;GET /sessions&#x22;: { description: &#x22;List sessions, filterable by environment_id, provider_key, status.&#x22; },
  &#x22;GET /sessions/{id}&#x22;: { description: &#x22;Get one session.&#x22; },
  &#x22;PUT /sessions/{id}/intent&#x22;: { description: &#x22;Update the agent-readable intent for the session.&#x22; },
  &#x22;POST /sessions/{id}/drafts&#x22;: { description: &#x22;Submit function source as a draft.&#x22; },
  &#x22;POST /sessions/{id}/attempts:compile&#x22;: { description: &#x22;Compile a draft through the governed function runtime.&#x22; },
  &#x22;POST /sessions/{id}/attempts:dry-run&#x22;: { description: &#x22;Run a compiled draft against non-production inputs.&#x22; },
  &#x22;POST /sessions/{id}/repairs&#x22;: { description: &#x22;Link a failed attempt to the next draft with a repair reason.&#x22; },
  &#x22;POST /sessions/{id}/readiness:evaluate&#x22;: { description: &#x22;Evaluate the deployment-readiness gate.&#x22; },
  &#x22;POST /sessions/{id}/proposals&#x22;: { description: &#x22;Create a deployment proposal once evidence is satisfied.&#x22; },
  &#x22;GET /sessions/{id}/timeline&#x22;: { description: &#x22;Drafts, attempts, repairs, proposals, and receipts for replay.&#x22; },
  &#x22;POST /sessions/{id}:archive&#x22;: { description: &#x22;Archive a session without touching runtime state.&#x22; },
  &#x22;GET /compile-attempts/{attempt_id}&#x22;: { description: &#x22;Fetch one compile attempt for review.&#x22; },
  &#x22;GET /dry-run-attempts/{attempt_id}&#x22;: { description: &#x22;Fetch one dry-run attempt for review.&#x22; },
  &#x22;POST /proposals/{proposal_id}:attach-to-workspace&#x22;: { description: &#x22;Stage a ready proposal into the operations workspace.&#x22; },
}"
/>

## Walking a session [#walking-a-session]

<Steps>
  <Step>
    ### Create a session and declare intent [#create-a-session-and-declare-intent]

    A session pins the `provider_key`, `integration_key`, `function_name`, and
    `function_kind` you are authoring for, plus an `environment_id`. Intent is the
    agent-readable description of what the function should do; set it at creation or
    update it later with `PUT .../intent`.

    ```bash
    curl -X POST http://localhost:8080/api/connectors/authoring/sessions \
      -H "X-Tenant-ID: $DUCTOR_TENANT_ID" \
      -H "Content-Type: application/json" \
      -d '{
        "environment_id": "env-dev",
        "provider_key": "acme-crm",
        "function_name": "upsert_contact",
        "function_kind": "mutation"
      }'
    ```
  </Step>

  <Step>
    ### Submit a source draft [#submit-a-source-draft]

    Post the generated function `source` for the session. Ductor stores a
    **hash-bound redacted source reference** in the authoring record, not
    unrestricted raw source — the draft is content-addressed and its provenance
    (`generated_by`, `provenance`) is captured. Chain iterations with
    `parent_draft_id` and a `reason`.
  </Step>

  <Step>
    ### Compile, then dry-run [#compile-then-dry-run]

    `attempts:compile` runs the draft through the governed connector-function
    runtime. Once a draft compiles, `attempts:dry-run` executes it against
    **sandbox, fixture, or other non-production** inputs — `allows_production_data`
    defaults off and must be set deliberately. Fetch a specific attempt later with
    `GET /compile-attempts/{id}` or `GET /dry-run-attempts/{id}`.

    <Callout type="warn">
      Dry-run is for test inputs. Do not point it at production payloads unless your
      environment and entitlements explicitly permit it via `allows_production_data`.
    </Callout>
  </Step>

  <Step>
    ### Record repairs [#record-repairs]

    When a compile or dry-run fails, `POST .../repairs` links the failed attempt to
    the next draft and a repair reason. This is what makes the fix history a
    first-class, replayable lineage rather than a series of disconnected edits.
  </Step>

  <Step>
    ### Evaluate readiness [#evaluate-readiness]

    `readiness:evaluate` is the gate. It returns `allowed` plus a list of
    `blockers`, each with a `surface`, `reason_code`, and `detail`. Surfaces cover
    setup readiness, permissions, entitlements, mutation semantics, field catalog,
    secret references, certification, promotion, artifact graph, and rollout
    evidence. You cannot create a proposal while blockers remain.
  </Step>

  <Step>
    ### Propose and attach to the workspace [#propose-and-attach-to-the-workspace]

    `POST .../proposals` is accepted only after compile, dry-run, and readiness
    evidence are satisfied. `POST /proposals/{id}:attach-to-workspace` then stages
    the ready proposal into the governed operations workspace and returns a
    **proposed change** — the hand-off into your normal promotion and rollout flow.
  </Step>
</Steps>

## Audit and replay [#audit-and-replay]

`GET /sessions/{id}/timeline` returns the full record — drafts, compile and
dry-run attempts, repairs, proposals, and receipts — for one session. Because
every step is content-addressed and linked, the timeline is a complete,
replayable audit of how a function was authored and verified. `:archive` retires
a session without mutating any connector runtime state.

## How this relates to the rest of connectors [#how-this-relates-to-the-rest-of-connectors]

Generated configuration enters the existing connector lifecycle only after the
ready proposal is attached to the operations workspace. From there, certification
scorecards, deployment diffs, destructive-change previews, and promotion gates
decide whether it can become active connector behavior.

<Cards>
  <Card title="Building a Provider" href="/docs/connectors/building-a-provider" description="The manual declarative and hand-written Go paths. Assisted Authoring is the agent-in-the-loop alternative to these." />

  <Card title="Certification & Testing" href="/docs/connectors/certification-and-testing" description="The certification gate a proposal must still clear before promotion." />

  <Card title="Marketplace & Deployments" href="/docs/connectors/marketplace-and-deployments" description="Where a proposed change goes once it leaves the workbench." />

  <Card title="Action Connections" href="/docs/management/connections" description="The operational credential bindings connector actions dispatch through." />

  <Card title="AI & Agents" href="/docs/ai" description="Governed agent surfaces — presets, tool security, and inference — that drive the authoring loop." />
</Cards>
