Extension ports¶
Five typed protocols keep the SDK open. An implementation ships in its own distribution and declares an entry point; nothing in the SDK changes.
| Port | Module | Entry-point group | Reference implementation |
|---|---|---|---|
SourceAdapter |
ports.source_adapter |
agent_connector_sdk.source_adapters |
mcp_tool |
ArtifactKind |
ports.artifact_kind |
agent_connector_sdk.artifact_kinds |
tools, skills, prompts, resources |
Transport |
ports.transport |
agent_connector_sdk.transports |
mcp |
Sink |
ports.sink |
agent_connector_sdk.sinks |
epistemic_graph |
WriteBackPort |
ports.writeback |
generated connector binding | GovernedWriteBack + fixture transport |
SourceAdapter¶
| Method | Contract |
|---|---|
describe() |
capabilities, without I/O |
discover(session) |
verify the live source contract; required before extraction |
extract(session, checkpoint) |
one page and the provider checkpoint that resumes after it |
reconcile(session, known_ids) |
ids missing from the source and unknown to the sink |
The mcp_tool adapter extracts through a connector's MCP tool as a preset
describes it (pagination, a since-watermark), requires the pinned
tool_schema_sha256, and rejects records that do not match the preset. The
watermark advances only when a sweep is exhausted.
pagination |
Parameters | Next page |
|---|---|---|
none |
none | |
cursor |
cursor_param; cursor_path or cursor_record_field; optional more_path |
the token, until it is absent or repeats |
page |
page_param, page_size_param, page_size, start_page; page_kind number (the spelling page is rejected) |
the next page index, until a page is shorter than page_size |
offset |
page_param (the offset), page_size_param, page_size; page_kind offset |
the offset plus the records returned, until a page is shorter than page_size |
A page_kind that does not apply to the mode is rejected. A preset with an
empty id_field is rejected: a sweep without record identity, such as a SQL
table sweep, belongs to a data-platform source adapter.
The package validator requires the current fingerprint algorithm and rejects a
tool_schema_sha256 derived from an empty input schema. The pin binds both
input and output schemas. An action selected by a preset must appear in the
action argument's JSON Schema enum (or its single-value const form).
Certify from the server's tools/list with
connector-certify.
ArtifactKind¶
Prompt packs read both prompts/list and prompts/get through the same MCP
session. Each prompt entry retains its listing definition, the argument contract,
and the complete ordered MCP result, including roles, typed multimodal content,
resource references and response metadata. The capture records that it is a
rendered prompt with no supplied arguments; it does not claim to be a template
or a system prompt. Changed message content changes the pack digest.
Pack provisioning has no configured prompt-argument input. A prompt with required arguments fails closed before retrieval; no values are invented. Optional arguments are omitted so the server may apply its defaults. Empty, incomplete or malformed results are rejected. Aggregate prompt capture uses the existing 16 MiB response-byte limit and fails before a pack can be acknowledged.
Sink¶
| Method | Contract |
|---|---|
submit(batch) |
commit a record batch; the receipt is returned only after commit |
source_status(connector, stream) |
read EG's sole durable checkpoint and live-set authority |
import_pack(pack) |
import a content pack keyed by its digest |
readiness() |
whether this sink can commit right now, without side effects -- returns a SinkReadiness(ready, reason); reason is set whenever ready is False and must never carry a credential or other secret value |
The connector-sync runner's /health/ready (see Connector sync
"Health") calls readiness() directly, bounded by a short timeout, so a sink
implementation must answer it without a side effect and should not assume it
is ever skipped. epistemic_graph requires a verified client and a live
ConnectorPack authority resolver at construction; the testing kit's
InMemorySink always reports ready.
SourceIngestionRequest is imported from
epistemic_graph.generated.source_ingestion; the SDK does not define an alias,
parallel DTO, or digest. Its generated canonical_digest() binds raw records,
provenance, exact per-record mapping references, provider checkpoint, and
expected previous checkpoint. The runner sends it through generated
send_source_ingest with a stable idempotency key and advances the checkpoint
only from the matching generated receipt. EG compare-and-swaps the expected
position atomically with the commit.
A mapping reference names one exact mapping the connector declares at
connector://resources: connector:<connector>#mappings/<key>. A relation
reference is connector:<connector>#relations/<resource>/<relation>. The
shorter connector:<connector> form is a convenience only for a declaration
holding exactly one mapping. Package validation fails closed when the short
form is ambiguous or an explicit fragment names no declared key. Other
reference schemes are rejected at the EG boundary.
Lifecycle mode is explicit on every page. full is a non-authoritative load,
delta may carry provider-declared withdrawals, and reconcile carries the
complete authoritative live-id and relationship sets so EG derives removals
atomically. Empty authoritative full/reconcile commits require a non-empty
descriptor approval and the verified server's source:reconcile-empty scope;
the SDK cannot grant that capability. Provider content hashes are optional and
are echoed, never invented. An unchanged empty delta is not submitted as a
fake checkpoint advance.
SourceIngest is the one durable operation; SQL batches and pre-mapped change
envelopes are not substitutes. EG resolves the manifest mapping, admits raw
evidence, deduplicates, writes provenance/outbox state, and advances the
checkpoint before returning SourceIngestionReceipt. The SDK verifies that the
receipt's batch digest, mode, and accepted checkpoint bind the submitted
request.
Runner ports¶
The connector-sync runner adds two runtime ports, described in
Connector sync: ConnectorRegistry
(ports.connector_registry) and ChangeSource (ports.change_source). Source
checkpoint and live-set state are read directly from EG's generated
SourceIngestStatus contract and are never persisted by the SDK.
WriteBackPort¶
WriteBackPort is the D18 source-I/O boundary. It reads the current source
version, produces a side-effect-free field diff, rejects an optimistic conflict
before mutation, verifies an exact durable authorization decision, applies under
an idempotency key, and reconciles every possible effect before retry. The only
authorization modes are proposal_approval, standing_policy, and
manual_trigger; a mode or reference supplied by a caller grants nothing by
itself.
Write-back sequence
GovernedWriteBack reads the source's current state (read_current),
compares the base version and field scope, then has
AuthorizationVerifier verify the exact digest/mode/ref/policy before
calling the WriteBackTransport's compare-and-apply with an idempotency
key. When acknowledgement is certain, the transport returns a source
observation directly. When the effect is only possible (an ambiguous
response), the transport reports the outcome as uncertain and
GovernedWriteBack reconciles using the key and source version, which
resolves to applied, no-effect, or still-uncertain. Either way, the final
source observations go back to EG's change set for durable receipts.
The canonical models come from epistemic_graph.generated.write_back.
SourceChangeSet.canonical_digest() and .patch_digest() implement EG's framed
MessagePack digest contract; the SDK neither reconstructs those schemas nor
implements a parallel digest. EG alone creates and persists WriteBackReceipt
and ReconciliationReceipt. No live vendor write-back is enabled by the
reference in-memory transport.
Activation¶
load_extension(group, name, policy=...) loads an extension only when the
activation policy certifies its exact group, name, distribution and version.
There is no permissive default. sdk_reference_extensions() certifies the
implementations this SDK version ships. Two distributions declaring the same
name in a group is an error.
Contract ownership¶
Source ingestion, ConnectorPack, and WriteBack request/result models come
directly from epistemic_graph.generated. The SDK owns only connector authoring,
capture, transport, and extraction shapes; it defines no parallel EG DTO or
digest.
Current-plan values¶
agent_connector_sdk.current_plan exports CurrentPlanRequest, PlanItem, CurrentPlanSnapshot and CurrentPlanRead. The request selects only a run ID. Snapshots carry a nonnegative revision, UTC observation and expiry, and ordered immutable items. An available read contains a snapshot, which can have no items. An unavailable read has no snapshot. All models reject unknown fields and coercion. Use model_validate_json for JSON input and model_dump_json for output.
The models validate shape and the timestamp interval. They do not establish caller authority, run ownership, current freshness or a live lease. The serving owner must verify those conditions before returning an available read.