Unified Capabilities

ReActCapabilities lets one structured reasoning conversation use native callable goals, MCP tools, UTCP endpoints, A2A agents and selected OpenAPI operations. The model sees named capabilities with argument contracts. ASTRA chooses and configures the implementation behind each name.

Separate the contract from its transport

A name such as add describes an operation to the model. Its binding may use MCP today and another implementation later. Give the model a precise description and schema, and keep transport setup in the application’s configuration plans.

The shared dispatcher lives in astra-langchain4j. Standalone adapters live in astra-langchain4j-tools; MAMS adapters use resources instead. Local callable goals execute through native invoke, retaining ordinary ASTRA goal failure and guard behaviour.

Bind capabilities

This configuration fragment is taken from the mixed capability example. It assumes an agent extending ReActCapabilities, a connected MCP module named mcp and a connected UTCP module named utcp:

tools.registerCallables();
capabilities.bindMCP("add", mcp.instance(), "math__add", tools.catalog());
capabilities.bindUTCP("increment", utcp.instance(), "http__add", tools.catalog());
!solve("Double 7, then add 1 twice", string answer);

Declare double with @Callable and provide its native plan. The transport catalogues used during discovery can remain separate from the semantic catalogue passed to the model.

The complete capabilities example adds A2A, a scripted model and local fixtures. The OpenAPI example imports selected operations into the same conversation. Their POMs specify the versions tested by those examples.

A2A and OpenAPI contracts

An A2A Agent Card describes skills; it does not supply a complete JSON contract for each operation. bindA2A therefore requires explicit input and output schemas, an endpoint, a skill and an HTTP implementation. The dispatcher validates arguments and the returned JSON.

OpenAPI bindings import selected operations from supported OpenAPI 3.0/3.1 JSON descriptions. The implementation supports local references, path/query/header parameters, JSON bodies and validated responses, with configured API-key, basic or bearer authentication. It is not a promise to support every OpenAPI feature. Consult the example’s profile before importing an unfamiliar specification.

Discovery is a separate decision

Discovery produces candidates. The application selects a candidate and binds the intended operation; discovering a service does not automatically expose all its functions to the model. Discovery bindings can carry lifetime guards, and withdrawal or expiry invalidates guarded bindings.

See the discovery examples and their DISCOVERY.md for supported profiles. Keep discovery policy in ASTRA: select by the application’s requirements, rather than accepting every advertised tool.

Completion and cleanup

Remote dispatch returns a correlated call ID and completes through native events. ReActCapabilities handles these events and resumes the waiting intention with the payload or error. Its direct !use(name, arguments, result) goal can also invoke a capability without asking the model to select one.

The default dispatch deadline is 30 seconds. Cancellation ends the local continuation and ignores late completion; it cannot guarantee rollback of external effects. A2A calls also expose task ID, context ID and task state through the dispatcher.

When retiring the integration, stop the dispatcher and each owned adapter. capabilities.stop() does not replace closing MCP sessions or other application-owned services. Unbind an operation when it should no longer be available.