Import message types from another package
Find a published package with axiom search and axiom info, pull its message types into your package with axiom import, and use them as node inputs and outputs.
View as MarkdownEvery node input and output is a message — a Protocol Buffers type. Messages
do not have to be defined in your own package: axiom import downloads the
.proto definitions from any published package so your nodes can consume or
produce its types. This is how packages — even in different languages — share
a contract: a flow can wire another package's node output straight into your
node's input because both sides reference the same message type. See
the type system for how edges type-check.
Prerequisites
- An Axiom package directory (one containing
axiom.yaml) — create one withaxiom init, see write your first node. - Logged in via
axiom login.axiom importrequires it;axiom searchandaxiom infowork without authentication. - For Go, Python, and TypeScript packages,
axiom importfinishes by runningaxiom generate, which uses the same proto tooling as the rest of the local loop (protoc+protoc-gen-gofor Go;grpcio-toolsorprotocfor Python;protoc+protoc-gen-js+protoc-gen-tsfor TypeScript). Rust, Java, and C# packages need no extra tooling — their protos compile during the language build.
The fast path
# Run inside your package directory (where axiom.yaml is).
axiom search --type messages TokensResult # which package defines the type?
axiom info axiom-official/axiom-text-ops # inspect its nodes and messages
axiom import axiom-official/axiom-text-ops # download protos, update axiom.yaml, generate
axiom create node Analyze --input TokensResult --output AnalysisReportAfter axiom import, the imported message types appear in
axiom create node's message list and work as --input/--output exactly
like messages defined in your own messages/messages.proto.
Search the marketplace
axiom search queries the marketplace; no login is needed.
axiom search # list recently published packages
axiom search text-ops # packages matching "text-ops"
axiom search --type nodes "tokenize" # search nodes instead
axiom search --type messages TokensResult # search messages instead--type (shorthand -t) selects what to search: packages (the default),
nodes, or messages. Package results list name, version, language, node
count, and author. Node and message results include the package and version
that publish them — so --type messages answers "which package do I import
to get this type?"
Inspect a package before importing
axiom info shows the full details of a published package; no login is
needed.
axiom info axiom-official/axiom-text-ops # most recently published version
axiom info axiom-official/axiom-text-ops@0.1.0 # a specific versionWhen @version is omitted, the most recently published version is shown.
The output includes the description, author, license, and deploy status; the
package's live endpoint URL; links to its openapi.json and interactive API
docs (see use the interactive API docs);
every node with its input → output message types; and every message the
package defines — the names you can use after importing.
A package can be proto-only: no nodes, just message types published for other packages to import. See nodes, packages, and flows.
Import the message types
# Run inside your package directory (where axiom.yaml is).
axiom import axiom-official/axiom-text-ops # latest version
axiom import axiom-official/axiom-text-ops@0.1.0 # pinned versionaxiom import requires a prior axiom login and must run inside a package
directory. It does four things:
- Resolves the version (the most recently published one when
@versionis omitted) and downloads the package's.protofiles. - Extracts them to
imports/<package>/<version>/. A scoped name's/becomes-in the directory name, soaxiom-official/axiom-text-ops@0.1.0lands inimports/axiom-official-axiom-text-ops/0.1.0/. - Records the dependency in
axiom.yamlunderimports:with the package, version, and imported message names. - Runs
axiom generateso the language bindings appear undergen/immediately.
If an imported message has the same name as one in your local messages/,
the import fails with a collision error before writing anything — rename one
of the two first.
Commit imports/ and the updated axiom.yaml to your repository:
axiom push builds your package from your git remote's HEAD commit, not
your working tree, so unpushed import files would be missing from the build.
What axiom import writes
After importing, axiom.yaml carries the pinned dependency:
# axiom.yaml (excerpt written by axiom import)
imports:
- package: axiom-official/axiom-text-ops
version: 0.1.0
messages:
- TextRequest
- TokensResultand the raw proto definitions live in your repository. The registry names
each downloaded file after the first message it defines (snake_case), not
after the upstream file name — here the package's TextRequest and
TokensResult share one proto file, downloaded as text_request.proto:
imports/
└── axiom-official-axiom-text-ops/
└── 0.1.0/
└── text_request.protoEach entry pins an exact version. Re-running the same import is safe — it merges any newly published message names into the existing entry. Importing a different version of the same package adds a second entry and a second directory side by side; nothing is upgraded implicitly.
Where the generated bindings go
- Go —
gen/imports/<package>/<version>/(Go protobuf bindings). - Python — one module per imported package, named after it:
gen/axiom_official_axiom_text_ops_messages_pb2.pyfor the example above. - TypeScript —
gen/imports/<package>/<version>/, one<file>_pb.jsplus a<file>_pb.d.tstype surface per downloaded proto file:text_request_pb.jsandtext_request_pb.d.tsfor the example above. - Rust, Java, C# — nothing at import time; the protos compile during the
language build (
build.rs/tonic-build for Rust, the protobuf-maven-plugin for Java, Grpc.Tools for C#).
Use an imported message in a node signature
Reference imported messages by their simple name, exactly like local ones.
axiom create node lists them in its interactive message picker alongside
local messages, accepts them for --input/--output, and prints a note
about their origin:
# Run inside your package directory, after axiom import.
axiom create node Analyze --input TokensResult --output AnalysisReport
# Note: TokensResult is from imported package "axiom-official-axiom-text-ops@0.1.0"The node's entry in axiom.yaml uses the simple name (input: TokensResult);
Axiom resolves which package it comes from via the imports: section. For
Go, Python, Java, C#, and Rust, the scaffolded node file already contains the
correct import statement. For TypeScript, the scaffold always imports from
../gen/messages_pb (the local messages module) — edit that line to point at
the imported module path shown below.
A complete Go example
A Go node whose input type comes from the imported package and whose output
type is local. Replace axiom-analytics with the module path from your
package's go.mod:
// nodes/analyze.go — input imported from axiom-official/axiom-text-ops
package nodes
import (
"context"
"fmt"
"strings"
"axiom-analytics/axiom"
gen "axiom-analytics/gen"
axiomtextops "axiom-analytics/gen/imports/axiom-official-axiom-text-ops/0.1.0"
)
// Analyze accepts tokenized text and produces a summary report with the
// token count and a human-readable listing of the tokens.
func Analyze(ctx context.Context, ax axiom.Context, input *axiomtextops.TokensResult) (*gen.AnalysisReport, error) {
return &gen.AnalysisReport{
Summary: fmt.Sprintf("Processed %d tokens: %s", input.GetCount(), strings.Join(input.GetTokens(), ", ")),
WordCount: input.GetCount(),
}, nil
}Import statements per language
For a message TokensResult imported from
axiom-official/axiom-text-ops@0.1.0:
# nodes/analyze.py — Python: per-package module under gen/
from gen.axiom_official_axiom_text_ops_messages_pb2 import TokensResult// nodes/analyze.ts — TypeScript: module under gen/imports/, named after the proto file
import { TokensResult } from '../gen/imports/axiom-official-axiom-text-ops/0.1.0/text_request_pb';// nodes/analyze.rs — Rust: imported messages compile into the same module as local ones
use crate::gen::messages::TokensResult;// nodes/Analyze.java — Java: fully qualified type in the imports.* namespace
import imports.axiom_official.axiom_text_ops.TokensResult;// nodes/analyze.cs — C#: bring in the imports.* namespace, then use the simple name
using imports.axiom_official.axiom_text_ops;Java and C# derive the namespace from the package name: / becomes . and
- becomes _, so axiom-official/axiom-text-ops becomes
imports.axiom_official.axiom_text_ops. Local messages stay where they
always are: gen.Messages.<Name> in Java, the Gen namespace in C#.
Troubleshooting
- "message X is listed in axiom.yaml imports but its proto definition is
not downloaded" —
axiom.yamldeclares the import but the files underimports/are missing (for example, a fresh checkout whereimports/was never committed). Run theaxiom import <package>@<version>command the error message prints. - "import collision: message X exists in both your local messages/ and the imported package" — two messages with the same name cannot coexist. Rename your local message (or import a package that doesn't clash), then re-run the import.
- "axiom.yaml not found — run this command from an Axiom package
directory" —
axiom importonly works inside a package directory;cdinto the directory created byaxiom initfirst. - "Not logged in" — run
axiom login. Search and info work logged out; import does not.
Next steps
- The type system — how messages type-check across flow edges.
- Push the package and build your first flow — wire your node up in the canvas.
- axiom.yaml reference — the full
imports:schema. - axiom import, axiom search, and axiom info — generated CLI reference for the three commands.