Skip to content
AIPDocs
Release status
DocumentationAIP 1.0GuideBuild with AIP

Use the Rust SDK

Use this guide when a Rust application needs AIP 1.0 types, validation, or an embedded protocol service. You will pin the reviewed SDK source, construct and validate one native action envelope, and then select optional modules by role. The procedure is for application developers who can change a Cargo manifest.

At source revision 97be86e9efedf07ecf1783b03800f683f107fb04, every AIP workspace package has publish = false. Consume that revision from source or from an approved mirror; do not assume that aip = "1" resolves to an AIP-owned registry release. The examples and commands on this page were checked against source without building the workspace or running an AIP service.

Prerequisites

You need:

  • Rust 1.88 or newer, matching the reviewed workspace minimum;
  • a Rust toolchain that supports edition 2024 packages;
  • access to the reviewed source revision or an approved immutable mirror of it;
  • permission to update and retain the project’s Cargo.toml and Cargo.lock;
  • a decision about whether the project needs only protocol semantics or also a runtime, transport, profile, or connector role.

No provider credential is required for the semantic example. Do not place credentials, tenant identifiers, or deployment secrets in a Cargo feature or source URL.

1. Choose the dependency boundary

The aip facade is the single entry crate that re-exports the semantic core and feature-gated modules from role-specific crates. Start with the smallest boundary that owns the API you need.

Boundary Use it when Initial choice
aip facade with defaults The application creates, parses, serializes, or validates native AIP values Prefer for most semantic consumers
aip facade with selected features The application embeds one or more re-exported service roles Add only the named role features
aip facade with full-core Integration or conformance work needs nearly every product-neutral facade module Use deliberately, then inspect the dependency tree
A role-specific crate A component needs a narrow compile-time boundary or a workspace role not re-exported by aip Depend on that crate directly

The facade always re-exports aip-core. Its default features are the std and json compatibility markers; they do not enable the runtime, gateway, transport, profile, schema, storage, conformance, or connector modules.

The facade is not an inventory of every workspace crate. Fleet admission, orchestration, control-plane, host-bootstrap, and shared MCP-session roles are direct crates at the reviewed revision.

2. Pin the reviewed source

Add the facade and JSON support to your application. A Git dependency records the immutable revision in Cargo.lock:

[dependencies]
aip = { git = "https://github.com/getaip/core", rev = "97be86e9efedf07ecf1783b03800f683f107fb04" }
serde_json = "1"

If policy requires a vendored checkout, replace the Git dependency with the approved local path:

[dependencies]
aip = { path = "../aip-core/crates/aip" }
serde_json = "1"

A path dependency does not record the checkout’s Git revision in the consumer lockfile. Record and verify the vendored source identity through the deployment or software bill of materials (SBOM) process responsible for that checkout.

3. Construct and validate an envelope

Create src/main.rs with a semantic-only example:

use aip::{
    Action, CapabilityId, Envelope, MessageBody, Principal, PrincipalId, PrincipalKind,
    validate_envelope,
};
use serde_json::json;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let action = Action::new(
        CapabilityId::parse("cap:example:echo")?,
        json!({ "message": "hello from Rust" }),
    );

    let mut envelope = Envelope::new(MessageBody::Action(Box::new(action)));
    envelope.from = Some(Principal::new(
        PrincipalId::parse("agent:sdk-example")?,
        PrincipalKind::Agent,
    ));

    validate_envelope(&envelope)?;
    println!("{}", serde_json::to_string_pretty(&envelope)?);
    Ok(())
}

Action::new generates an action identifier. Envelope::new derives the message type, generates a message identifier, sets aip_version to 1.0, and records the current UTC time. The printed JSON therefore changes on every run.

validate_envelope checks semantic invariants such as the protocol version, the message-type/body match, identifiers, and body-specific requirements. It does not authenticate from, authorize the capability, admit a manifest, or dispatch the action. A gateway or protocol endpoint owns those boundaries.

4. Verify the semantic project

Generate and retain a lockfile before using --locked:

cargo generate-lockfile
cargo check --locked
cargo run --locked

Expected result: the project compiles and prints a JSON envelope containing "aip_version": "1.0", "message_type": "aip.core.v1.action", an action body, and the agent:sdk-example sender. Generated identifiers and sent_at will differ between runs.

Inspect the enabled facade features:

cargo tree --locked -e features -p aip

For the initial example, the facade should not show optional runtime, gateway, transport, profile, schema, storage, conformance, or connector features. A successful compile proves only that this consumer and dependency graph compile; it is not protocol conformance, deployment readiness, or provider qualification.

5. Add features by task

Enable a feature only when its public module belongs in the current component. Feature implications in this table are the explicit facade relationships at the reviewed revision.

Task Facade feature Important implication
Generate or validate against the schema registry schema Exposes aip::schema
Compose authentication and authorization primitives auth Exposes aip::auth
Sign, verify, or canonicalize native values crypto Exposes aip::crypto; it does not define authorization policy
Admit and query manifests discovery Exposes aip::discovery
Run durable action and session services runtime Also enables auth and discovery
Embed the gateway composition layer gateway Also enables runtime
Persist runtime state in PostgreSQL storage-postgres Also enables runtime
Use the shared transport abstraction transport Exposes aip::transport without selecting a wire binding
Use a native wire binding transport-http, transport-nats, transport-sse, or transport-websocket Each also enables transport
Translate a compatibility protocol profile-mcp, profile-a2a, or profile-webhook Exposes only the selected profile mapping
Embed an outbound MCP client mcp-client Also enables profile-mcp
Embed an AIP-backed MCP server mcp-server Also enables gateway and profile-mcp
Check the MCP compatibility mapping mcp-conformance Also enables profile-mcp
Use an MCP transport transport-mcp-stdio or transport-mcp-streamable-http Also enables transport and profile-mcp
Use the product-neutral connector contract connector Exposes aip::connector
Host one immutable connector artifact connector-host Also enables connector and connector-registry
Read or implement fleet registry contracts connector-registry Also enables connector
Persist the fleet registry in PostgreSQL connector-registry-postgres Also enables connector-registry
Dispatch to a remote connector host connector-remote Also enables connector-registry
Add metrics and tracing conventions observability Exposes aip::observability
Build deterministic tests testkit Exposes aip::testkit
Run implementation conformance checks conformance Exposes aip::conformance
Enable every product-neutral facade role full-core Excludes product connector features by an enforced source gate

For example, a component that embeds a gateway and exposes an HTTP transport can select those roles explicitly:

[dependencies]
aip = { git = "https://github.com/getaip/core", rev = "97be86e9efedf07ecf1783b03800f683f107fb04", features = ["gateway", "transport-http"] }

Selecting a feature makes its module available. It does not configure an identity resolver, policy, storage backend, transport listener, manifest, handler, connector registry, or credential provider.

6. Use role-specific crates when ownership matters

Choose a direct crate when a component should expose only one role or when the facade does not re-export that role.

Role Direct dependency Boundary owned by the crate
Protocol semantics aip-core Native types, identifiers, serialization, and pure validation
Schema tooling aip-schema Schema registry, generation, compilation, and validation helpers
Identity and cryptography aip-auth, aip-crypto Policy primitives and cryptographic primitives remain separate
Discovery aip-discovery Manifest registry, admission policy, cache, and profile negotiation
Execution aip-runtime, aip-gateway Durable lifecycle services and gateway composition
Transports aip-transport and aip-transport-* Shared transport contract and individual bindings
Compatibility profiles aip-profile-*, aip-mcp-* Wire translation and MCP lifecycle roles
Connector implementation aip-connector Product-neutral connector traits and error contracts
Fleet data plane aip-connector-registry, aip-connector-host, aip-connector-remote Catalog, isolated host, route selection, and remote dispatch
Fleet lifecycle aip-connector-admission, aip-connector-orchestration, aip-connector-control-plane, aip-connector-host-bootstrap Verified admission, platform-neutral rollout, restricted lifecycle service, and host process shell
PostgreSQL persistence aip-storage-postgres, aip-connector-registry-postgres Runtime state and normalized fleet registry state
Testing aip-testkit, aip-conformance Deterministic fixtures and conformance checks

Direct dependencies still use the same exact source revision. Do not combine different AIP source revisions in one dependency graph unless a documented compatibility procedure explicitly permits it.

7. Keep legacy full out of new applications

full-core is the broad product-neutral feature group in the facade. A source gate follows every feature it enables and rejects the graph if a product connector feature or dependency becomes reachable.

full has a different purpose. The facade source labels it a legacy compatibility feature group. It adds a fixed set of product connector features to full-core, so it increases coupling and does not represent the current public connector catalog. New core consumers should use full-core, role features, or direct role crates. Add only the product dependency owned by the artifact.

To migrate an application away from full:

  1. replace full with full-core or a smaller explicit feature list;
  2. run cargo check once to resolve the changed graph and identify imports that depended on product code;
  3. add only the required product connector dependency through its documented integration boundary;
  4. inspect the manifest and lockfile diff, then run cargo check --locked and cargo tree --locked -e features against the reviewed result.

The repository’s registered examples still declare required-features = ["full"] at the reviewed revision. Running one of those exact examples inside the source workspace may therefore require the legacy flag:

cargo run --locked -p aip --example minimal-agent --features full

That requirement belongs to the repository example metadata. It is not a recommended dependency choice for a new application, and the authoring pass for this page did not execute the command.

8. Review and narrow the change

Before merging a dependency change, inspect both the declared and resolved surface:

cargo check --locked
cargo tree --locked -e features
git diff -- Cargo.toml Cargo.lock

Confirm that:

  • the dependency resolves from the approved source and revision;
  • full is absent unless an exact repository compatibility task requires it;
  • every enabled facade feature belongs to the component’s declared role;
  • product connector packages appear only when explicitly owned by that artifact;
  • the change contains no credential, internal endpoint, or local absolute path;
  • compilation is reported as compilation evidence, not conformance or runtime evidence.

If a feature is unnecessary, remove it from Cargo.toml, regenerate the lockfile, and repeat the checks. No runtime rollback is required for the semantic example because it performs no external operation. Existing Cargo build artifacts do not need to be deleted to narrow the dependency declaration.

Resolve common failures

Symptom Likely cause Bounded action
Cargo cannot find aip in a registry The manifest used registry version syntax for a package that is publish = false at this revision Use the pinned Git source or an approved vendored path
Cargo rejects the active toolchain The compiler is older than the workspace minimum Select Rust 1.88 or newer and rerun cargo check --locked
An import such as aip::gateway is missing Its facade feature is not enabled Add only the owning feature and inspect the feature tree
Product connector packages appear unexpectedly full or a direct product dependency is enabled Replace full, then trace the remaining product dependency with cargo tree
A repository example refuses to build without full Its registered metadata still requires the compatibility feature group Use full only for that exact example; do not copy it into the application manifest
The dependency graph is much larger than expected full-core or a high-level feature selected more roles than the component needs Replace it with the smallest task-specific features or direct role crates
Validation succeeds but dispatch later fails Semantic validation does not authenticate, authorize, admit, route, or execute Inspect the gateway or endpoint boundary that owns the failed stage

Dependency inspection and semantic validation are read-only with respect to provider state. They do not justify retrying an ambiguous provider mutation.