Reasoning Runtime and Modular Feature API
This guide explains how to use Tech Connector's API version 2 reasoning runtime, contextual threads, progress events, runtime tools, and modular feature registry.
For the complete older headless API reference, including action graphs, prompt chains, Python calls, and DCC calls, see HEADLESS_API.md. For every indexed DCC function and its arguments, see API_FUNCTION_CATALOG.md.
What This API Solves
The API lets scripts, services, tests, and other applications use the same request-understanding and routing system as Tech Connector without opening the Qt interface.
It provides:
- Project-aware request context
- Canonical conversation history
- Request preparation and code understanding
- Deterministic request routing
- Model route selection
- Integer progress and activity events
- Validation contracts
- Runtime tool discovery
- Approval-aware tool execution
- Modular feature discovery and extension
- Existing action graph, prompt chain, Python, and DCC execution APIs
Mental Model
The public API is divided into four layers:
flowchart LR
A["Your application"] --> B["TechConnectorHeadlessAPI"]
B --> C["Reasoning runtime"]
B --> D["Modular feature registry"]
B --> E["Action graphs and prompt chains"]
B --> F["Python and DCC execution"]
C --> G["RequestEngine"]
C --> H["Project-aware runtime adapters"]
D --> H
F --> I["Connected DCC bridges"]
Use the narrowest layer that fits the job.
| Goal | Recommended API |
|---|---|
| Understand and route a natural-language request | api.reasoning.run() |
| Inspect runtime context without dispatching | api.reasoning.snapshot() |
| Build sanitized request context and code understanding | api.reasoning.prepare() |
| Discover all current modules | api.features.manifest() |
| Discover one category | api.features.list(category=...) |
| Invoke one registered module operation | api.features.invoke() |
| Preview a deterministic action graph | api.plan_prompt() |
| Execute an approved action graph | api.execute_action_graph() |
| Run several natural-language steps | api.execute_prompt_chain() |
| Call normal Python | api.call_function() |
| Call Maya, Unreal, Blender, or another DCC | api.dcc.<host>... |
Applications Can Attach at Any Lifecycle Stage
An application does not have to wrap the entire Tech Connector runtime. Applications can consume or extend the specific lifecycle stages they own. For example, a DCC plugin may contribute host context and tools, a review service may attach to validation, and a custom UI may invoke planning and execution without reimplementing either one.
flowchart LR
U["Understand"] --> C["Context and evidence"]
C --> P["Plan"]
P --> G["Generate"]
G --> V["Validate"]
V --> R["Repair"]
R --> X["Execute"]
X --> O["Observe and complete"]
UI["Desktop or web UI"] --> U
CLI["CLI or automation"] --> P
DCC["Maya, Unreal, Blender, or MotionBuilder plugin"] --> C
DCC --> X
INDEX["Studio index or knowledge service"] -. registered evidence .-> C
GENERATOR["Custom code generator"] -. registered feature .-> G
REVIEW["Review or policy service"] -. registered validation .-> V
REPAIR["Studio repair provider"] -. registered repair capability .-> R
TELEMETRY["Monitoring or telemetry application"] -. events .-> O
U -. progress and results .-> UI
P -. plans .-> CLI
X -. bridge results .-> DCC
O -. activity stream .-> TELEMETRY
The horizontal chain is the request lifecycle. The surrounding boxes are applications or application-owned modules, not mandatory front ends.
| Integration need | Recommended attachment |
|---|---|
| Submit a complete natural-language request | reasoning.runtime |
| Analyze only request shape and scope | understanding.request_frame |
| Add thread, project, host, or permission context | runtime.context.* |
| Supply indexed symbols or external knowledge | runtime.index.*, runtime.knowledge.*, or runtime.symbol_lookup.* |
| Build or execute action graphs | planning.action_graph |
| Add a custom generator or studio operation | A registered direct feature |
| Contribute validation rules | runtime.validation.* |
| Execute inside a DCC | execution.dcc or a registered capability bridge |
| Observe progress and performance | Progress/activity events and models.inference_telemetry |
The feature descriptor tells a host application how it may attach:
access="direct"means the application may invoke the declared operations.access="owned"means the module participates at that lifecycle stage throughowner_feature_id.access="internal"means the component is visible for architecture and diagnostics but is not a standalone public entry point.lifecycle_stagetells graph-based UIs where the feature belongs.
A custom application feature can therefore declare its own graph placement:
api.features.register(
APIFeatureDescriptor(
feature_id="studio.material_review",
category="studio.review",
version="1.0",
description="Review generated materials before DCC execution.",
operations=("review",),
lifecycle_stage="validation",
access="direct",
source="studio_tools.material_review",
),
handlers={"review": review_material},
)
This places the application capability at validation without forcing it to become a complete chat client or replace the reasoning runtime.
Authentication
The API uses the user's Tech Connector login and saved settings. It does not require application code to contain an OpenAI, Anthropic, Google, or X API key.
from tech_connector.api import create_api
api = create_api(project_root="C:/my_project")
status = api.verify_license()
if not status.get("connected"):
raise RuntimeError(status.get("reason") or "Log in to Tech Connector first.")
Model-provider authentication follows the provider configuration selected in Tech Connector. The API-selected settings are passed into the reasoning runtime's model router.
require_entitlement=False is intended for status checks, diagnostics, and
tests. It should not be used to bypass execution entitlements.
Five-Minute Quick Start
from pathlib import Path
from tech_connector.api import create_api
api = create_api(project_root=Path.cwd())
result = api.reasoning.run(
"Find the implementation of create_rig_mapping and explain its dependencies",
context={
"active_tab": "API",
"project_roots": [str(Path.cwd())],
},
)
if not result.ok:
raise RuntimeError(result.error)
response = result.result["response"]
print("Action:", response["action"])
print("Label:", response["label"])
print(response["text"])
See reasoning_quickstart.py for a runnable version.
Understanding APIResult
Most operations return APIResult.
@dataclass(frozen=True)
class APIResult:
ok: bool
result: Any = None
error: str = ""
entitlement: dict | None = None
provenance: dict | None = None
Use it consistently:
result = api.reasoning.snapshot("Inspect the current project")
if result.ok:
payload = result.result
else:
print(result.error)
APIResult.to_dict() is convenient for logs, JSON responses, and test
assertions.
snapshot, prepare, and run
These operations are related but intentionally different.
api.reasoning.snapshot()
Use snapshot to inspect the installed runtime without dispatching the request
through the full request engine.
snapshot = api.reasoning.snapshot("Inspect the current project")
runtime = snapshot.result["runtime"]
print(runtime["model_route"])
print(runtime["tools"])
print(runtime["rule_sets"])
print(runtime["validation"])
The snapshot includes:
- Active domain context
- Interaction surface
- System instructions
- Runtime tools
- Validation reports
- Model route
- Installed rule sets
- Reasoning frame and diagnostics
- Adapter counts
api.reasoning.prepare()
Use prepare when another component needs a sanitized RequestContext and the
runtime metadata attached to it.
prepared = api.reasoning.prepare(
"Explain the selected code",
context={
"current_file_path": "C:/project/exporter.py",
"selection_text": "def export_fbx(...): ...",
"extras": {
"safe_project_label": "character_tools",
"api_key": "this value is removed",
},
},
)
context = prepared.result["context"]
assert "api_key" not in context["extras"]
prepare performs code-understanding work when providers are installed. It
does not execute a mutating action.
api.reasoning.run()
Use run to pass the request through the shared RequestEngine.
result = api.reasoning.run("Find function export_fbx()")
response = result.result["response"]
The response action determines what happened:
| Action | Meaning |
|---|---|
answer |
A deterministic or specialized route produced an answer |
clarify |
Required information or approval is missing |
error |
The request failed and APIResult.ok is false |
passthrough |
No specialized deterministic route completed the answer |
| Other registered action | A domain provider returned a typed workflow state |
passthrough is not the same as a completed model answer. It means the request
engine prepared and classified the request but no specialized provider handled
it. Callers should inspect response["prompt"], response["metadata"], and
their configured model transport before presenting it as complete.
Request Context
Context is optional information the calling application passes beside the prompt. It tells Tech Connector what the user is looking at, which project may be searched, and what prior conversation or domain state is relevant.
Context is not a second prompt, and none of its fields are required.
Smallest Possible API Request
result = api.reasoning.run("Explain how the feature registry works.")
Because this call came through the headless API, Tech Connector automatically
uses "API" as its interaction surface. The caller does not need to provide
active_tab.
What active_tab Actually Means
active_tab is the original desktop-compatible name for the application area
that originated the request. It is a descriptive string, not a fixed enum and
not a requirement that the caller has tabs.
API callers should normally use the clearer interaction_surface alias:
result = api.reasoning.run(
"Review the selected material definition.",
context={
"interaction_surface": "material_review_service",
},
)
The aliases below are equivalent:
{"active_tab": "Pipelines"} # Existing desktop callers
{"interaction_surface": "Pipelines"} # Preferred API spelling
{"surface": "Pipelines"} # Short API spelling
If the application is not an editor, pipeline, or any other example shown in this guide, use its own meaningful name:
{"interaction_surface": "asset_publish_dashboard"}
{"interaction_surface": "maya_shelf_tool"}
{"interaction_surface": "render_farm_worker"}
{"interaction_surface": "studio_review_bot"}
If no surface name would add useful information, omit it. The API defaults to
"API". The surface is a routing/context hint; it does not restrict which
features the request may use.
Supplying Project and Selection Context
Pass context using the context= argument on snapshot, prepare, or run:
result = api.reasoning.run(
"Explain the selected function and identify its callers.",
context={
"interaction_surface": "code_review_panel",
"current_file_path": "/workspace/project/tools/exporter.py",
"open_file_paths": [
"/workspace/project/tools/exporter.py",
"/workspace/project/tools/importer.py",
],
"selection_text": "def export_fbx(...): ...",
"project_roots": ["/workspace/project"],
"index_state": "ready",
},
)
| Field | Required? | What the caller enters | Default and behavior |
|---|---|---|---|
interaction_surface |
No | Any useful caller label, such as maya_shelf_tool |
Preferred API-neutral alias for active_tab; defaults to API |
active_tab |
No | Existing desktop area such as Editor or Pipelines |
Compatibility name; any string is accepted |
surface |
No | Short alias for interaction_surface |
Used only when active_tab is absent |
current_file_path |
No | Absolute path to the file the user is actively viewing | Highest-priority file context; empty when no file is active |
open_file_paths |
No | List of other relevant absolute file paths | Empty list |
selection_text |
No | Exact text or code explicitly selected by the user | Empty string; do not populate with an entire file automatically |
project_roots |
No | Directories Tech Connector may search and index | API project root, configured active project, and tools root |
attached_images |
No | Local image paths available to the runtime | Empty list |
model |
No | Provider-qualified or configured model name | Current API/settings model |
index_state |
No | Caller-known state such as ready, building, or stale |
unknown |
thread or messages |
No | Structured prior user/assistant turns | No prior conversation |
extras |
No | Additional non-secret domain data | Empty dictionary |
Custom Context That Is Not in the Table
Applications are expected to have domain-specific state. Put it in extras:
result = api.reasoning.run(
"Validate this publish request.",
context={
"interaction_surface": "asset_publish_dashboard",
"extras": {
"asset_id": "character.hero",
"publish_stage": "animation",
"review_status": "changes_requested",
},
},
)
For convenience, unknown top-level fields are also preserved under extras:
context = {
"interaction_surface": "asset_publish_dashboard",
"asset_id": "character.hero", # Moved to extras["asset_id"]
"publish_stage": "animation", # Moved to extras["publish_stage"]
}
Explicit extras is recommended for public integrations because it makes the
boundary clear.
Unknown top-level context fields are preserved under extras.
Credential-like keys are removed recursively. This includes API keys, access keys, secrets, tokens, passwords, credentials, authorization values, cookies, and private keys.
If the Request Matches No Specialized Feature
The request may still be submitted normally. Context fields describe where the request came from; they do not enumerate the kinds of requests Tech Connector accepts.
If no deterministic or domain provider owns the request,
api.reasoning.run() may return response["action"] == "passthrough". That
means the request was understood and prepared but still needs the configured
model transport or a custom registered feature. It must not be presented to
the user as a completed answer.
Contextual Threads
The API does not force the Qt transcript into memory. The caller owns the canonical structured thread and supplies it with each request.
thread = [
{
"role": "user",
"content": "We are building a Maya-to-Unreal animation sync tool.",
},
{
"role": "assistant",
"content": "The current focus is clip export and Unreal import.",
},
]
result = api.reasoning.run(
"Now add integer progress callbacks.",
context={"thread": thread},
)
After the response, append the new user and assistant turns to your stored thread. See thread_context_example.py.
The runtime receives canonical history independently of any UI rendering limit. For very long sessions, applications should retain:
- Recent turns verbatim
- A durable summary of older decisions and constraints
- References to generated files, assets, and symbols
- Archived full turns for search or user viewing
Progress and Activity Events
Progress callbacks receive JSON-safe dictionaries with integer progress values.
def on_progress(event):
current = event["current"]
total = event["total"]
print(f'{event["stage"]}: {event["message"]} ({current}/{total})')
def on_activity(event):
print(event["status"], event["title"], event["detail"])
result = api.reasoning.run(
"Find every rig export implementation",
progress_callback=on_progress,
activity_callback=on_activity,
)
The same events are retained in:
result.result["progress"]
result.result["activity"]
This supports streaming UIs, command-line progress, logs, and service status endpoints without parsing human-readable text.
Modular Feature Registry
The feature registry prevents the API from becoming one monolithic interface.
List Everything
manifest = api.features.manifest()
for feature in manifest["features"]:
print(
feature["feature_id"],
feature["access"],
feature["owner_feature_id"],
feature["operations"],
)
For an operation-level inventory of the high-level Python namespaces, use the separate public surface manifest:
surface = api.surface()
for operation in surface["operations"]:
print(operation["path"], operation["signature"])
The feature manifest describes modular capabilities and ownership. The surface
manifest describes concrete Python methods. Dynamic DCC functions, Kingdom
editor operations, runtime tools, and attached UI actions retain their own
authoritative catalogs, which are linked in surface["dynamic_surfaces"].
Filter by Category
contexts = api.features.list(category="runtime.context")
indexes = api.features.list(category="runtime.index")
validation = api.features.list(category="runtime.validation")
direct_features = api.features.list(access="direct")
validation_stages = api.features.list(lifecycle_stage="validation")
project_edit_modules = api.features.list(
owner_feature_id="code.project_edit_workflow",
)
Category filtering includes child categories. Access, lifecycle, and owner filters can be combined.
Inspect One Feature
feature = api.features.get("reasoning.runtime")
print(feature["description"])
print(feature["access"])
print(feature["owner_feature_id"])
print(feature["lifecycle_stage"])
print(feature["stability"])
print(feature["operations"])
print(feature["dependencies"])
print(feature["permissions"])
print(feature["source"])
Invoke One Operation
result = api.features.invoke(
"runtime.context.tech_connector_context",
"active_context",
)
print(result.result["value"])
Only operations declared by the descriptor can be invoked.
Features with access == "owned" are real modular stages, but their public
owner coordinates them so shared context, validation, and progress are not
bypassed. Features with access == "internal" are documented for architecture
and extension discovery; they are not standalone compatibility promises.
Feature Descriptor
Every feature provides:
| Field | Meaning |
|---|---|
feature_id |
Stable unique identifier |
category |
Filterable module group |
version |
Feature contract version |
description |
Human-readable purpose |
access |
direct, owned, or internal |
owner_feature_id |
Public feature responsible for an owned/internal stage |
lifecycle_stage |
Request lifecycle location |
stability |
Compatibility level, normally stable or internal |
operations |
Allowed direct invocation operations |
dependencies |
Required feature IDs or categories |
permissions |
Required approval or entitlement labels |
available |
Current availability |
source |
Implementing Python class or module |
operation_schemas |
Per-operation input/output schema |
metadata |
Adapter-specific discovery information |
Built-In Product Features
| Feature ID | Purpose |
|---|---|
reasoning.runtime |
Snapshot, prepare, and run requests |
reasoning.tools |
List and execute runtime tools |
planning.action_graph |
Plan and execute one action graph |
planning.prompt_chain |
Plan and execute sequential prompts |
code.pipeline_generation |
Generate pipeline Python |
execution.python |
Call normal Python |
execution.dcc |
Call a DCC function through a bridge |
intelligence.dcc_catalog |
Discover DCC API functions and aliases |
integrations.connected_services |
Connected-account status, smart references, targets, setup URLs, and approved dispatch |
api.surface |
Complete supported Python operation and signature inventory |
api.license |
Inspect entitlement state |
Tech Connector Lifecycle Features
The reasoning adapters are one layer of Tech Connector, not the whole modular system. The manifest also describes the modules used from initial request understanding through completion:
| Feature ID | Access | Owner | Lifecycle role |
|---|---|---|---|
understanding.request_frame |
direct | - | Request shape, host, scope, and constraints |
prompt.resource_orchestration |
direct | - | Goal-aware resource and model assignment |
context.conversation_workspace |
direct | - | Canonical thread/workspace compatibility snapshots |
quality.validation_plan |
direct | - | Focused validation planning for changed paths |
quality.validation_intent |
direct | - | Validation-request classification |
intelligence.tool_discovery |
direct | - | Source-backed callable discovery |
prompt.stage_quality |
owned | reasoning.runtime |
Pre-generation understanding and routing audit |
planning.implementation_contract |
owned | code.project_edit_workflow |
Per-symbol plans and cross-file contracts |
code.project_edit_workflow |
owned | reasoning.runtime |
Multi-file generation, project validation, and candidate production |
quality.project_edit_passes |
owned | code.project_edit_workflow |
Separate syntax, import, API, signal, dead-code, behavior, and final checks |
repair.convergence |
owned | reasoning.runtime |
Provider selection and monotonic validation-to-repair acceptance |
intelligence.project_index |
owned | reasoning.runtime |
Persistent exact index updates and evidence |
models.provider_routing |
owned | reasoning.runtime |
Local or login-backed model routing |
models.inference_telemetry |
owned | reasoning.runtime |
First-token, generation, and throughput telemetry |
execution.adaptive_goals |
owned | reasoning.runtime |
Per-goal evidence and confidence state |
execution.supervised_actions |
owned | planning.action_graph |
Action execution and repair supervision |
provenance.usage |
owned | code.pipeline_generation |
Generated-code and project provenance |
repair.symbol_chunks |
internal | code.project_edit_workflow |
Exact symbol-scoped repair enforcement |
ui.pipeline_node_graph |
internal | planning.action_graph |
Pipeline nodes, links, attributes, and smart menus |
ui.pipeline_utility_nodes |
internal | planning.action_graph |
Built-in utility-node catalog |
This access model avoids two equally harmful extremes: hiding useful modular capabilities, or exposing internal orchestration as if callers could safely run it without its owner.
Direct Lifecycle Examples
frame = api.features.invoke(
"understanding.request_frame",
"analyze",
prompt="Create a Maya exporter and Unreal importer.",
)
resources = api.features.invoke(
"prompt.resource_orchestration",
"plan",
prompt="Create a Maya exporter and Unreal importer.",
)
checks = api.features.invoke(
"quality.validation_plan",
"plan",
paths=["maya_tools/exporter.py", "unreal_tools/importer.py"],
project_root=api.project_root,
)
Each call returns APIResult. Its serialized value is in
result.result["value"].
Automatically Registered Runtime Features
Installed runtime adapters are registered from the actual kernel:
runtime.context.*runtime.reasoning.*runtime.capability.*runtime.validation.*runtime.code_policy.*runtime.rules.*runtime.code_understanding.*runtime.knowledge.*runtime.index.*runtime.symbol_lookup.*runtime.escalation.*
Passive typed providers remain independently discoverable even when their
execution is owned by reasoning.runtime.
Registering a Custom Feature
There are three different customization mechanisms:
| Goal | Use |
|---|---|
| Add a callable operation that applications invoke explicitly | api.features.register(...) |
| Replace one registered feature contract in this API object | api.features.register(..., replace=True) |
| Add context, tools, rules, validation, knowledge, indexes, or model policy to reasoning | create_api(runtime_packages=[...]) |
Registering a feature does not automatically insert it into every reasoning request. Runtime packages customize the reasoning pipeline. This distinction prevents an extension from silently changing unrelated requests.
Add a Callable Feature
This complete example registers an operation, invokes it, checks the result, and prints its returned value:
from tech_connector.api import create_api
from tech_connector.services.api_feature_registry_service import (
APIFeatureDescriptor,
)
def review_asset(asset_path="", ruleset="default"):
return {
"asset_path": asset_path,
"ruleset": ruleset,
"passed": True,
}
api = create_api()
api.features.register(
APIFeatureDescriptor(
feature_id="studio.asset_review",
category="studio",
version="1.0",
description="Review an asset against studio rules.",
operations=("review",),
permissions=("project_read",),
source="studio_tools.asset_review",
operation_schemas={
"review": {
"input": {
"asset_path": "string",
"ruleset": "string",
},
"output": "object",
}
},
),
{"review": review_asset},
)
result = api.features.invoke(
"studio.asset_review",
"review",
asset_path="/Game/Characters/SK_Hero",
ruleset="character",
)
if not result.ok:
raise RuntimeError(result.error)
print(result.result["value"])
# {
# "asset_path": "/Game/Characters/SK_Hero",
# "ruleset": "character",
# "passed": True,
# }
Registration rejects:
- Empty feature IDs
- Duplicate feature IDs unless
replace=True - Handlers not declared in
operations - Invocation of unavailable features
- Invocation of undeclared operations
See custom_feature_example.py.
Replace a Registered Feature
Replacement is explicit and local to one TechConnectorHeadlessAPI instance.
It does not rewrite source files or affect other API objects.
def strict_review_asset(asset_path="", ruleset="default"):
return {
"asset_path": asset_path,
"ruleset": ruleset,
"passed": bool(asset_path and ruleset != "disabled"),
"reviewer": "strict-v2",
}
api.features.register(
APIFeatureDescriptor(
feature_id="studio.asset_review",
category="studio",
version="2.0",
description="Review an asset with the strict studio policy.",
operations=("review",),
permissions=("project_read",),
source=f"{__name__}.strict_review_asset",
),
{"review": strict_review_asset},
replace=True,
)
result = api.features.invoke(
"studio.asset_review",
"review",
asset_path="/Game/Characters/SK_Hero",
ruleset="character",
)
assert result.ok
assert result.result["value"]["reviewer"] == "strict-v2"
Important replacement rules:
- Use the same
feature_idfor the feature being replaced. - Preserve operation names and compatible arguments when existing callers must continue working.
replace=Truechangesapi.features.invoke()dispatch for that API object.- Replacing a registry descriptor for an
ownedorinternalstage does not rewire its owner. Customize the runtime through a runtime package instead. - Create a separate feature ID when the old and new behavior should coexist.
See feature_replacement_example.py.
Customize the Reasoning Setup
A runtime package can contribute any adapter interface understood by
ReasoningKernel. The default Tech Connector package remains installed; the
supplied packages are added after it.
This complete example adds studio publish context:
from reasoning_runtime.adapters.context_adapter import (
ContextAdapter,
InteractionSurface,
)
from tech_connector.api import create_api
class StudioPublishContext(ContextAdapter):
"""Supply the active studio publish state."""
name = "studio_publish"
def get_active_context(self):
return {
"asset_id": "character.hero",
"publish_stage": "animation",
"review_status": "changes_requested",
}
def get_interaction_surface(self):
return InteractionSurface(
kind="asset_publish_dashboard",
supports_clarification=True,
supports_approval=True,
)
def get_permission_context(self):
return {
"can_read_project": True,
"can_publish": False,
}
class StudioRuntimePackage:
def get_context_adapters(self):
return [StudioPublishContext()]
api = create_api(runtime_packages=[StudioRuntimePackage()])
snapshot = api.reasoning.snapshot("What publish state is active?")
if not snapshot.ok:
raise RuntimeError(snapshot.error)
studio_context = snapshot.result["runtime"]["context"]["studio_publish"]
print(studio_context["asset_id"])
# character.hero
The installed adapter is also discoverable:
feature = api.features.get("runtime.context.studio_publish")
assert feature["access"] == "direct"
assert "active_context" in feature["operations"]
Use a runtime package for:
- context adapters
- reasoning adapters and prompt overlays
- capability bridges and tools
- validation contracts
- bounded repair providers
- evidence and escalation policies
- code-intelligence adapters
- knowledge, index, and symbol-lookup providers
- rule providers, action planners, and reasoning layers
Advanced callers that already own a fully configured ReasoningKernel may
pass it as runtime_kernel=kernel. When a kernel is supplied, Tech Connector
uses it as the base and then installs any runtime_packages.
See custom_runtime_package_example.py.
Runtime Tools and Approval
Runtime tools are finer-grained than product features. Every tool advertises:
- Input and output schemas
- Mutability
- Risk
- Permissions
- Execution target
- Examples and metadata
tools_result = api.reasoning.tools()
tools = tools_result.result["tools"]
for tool in tools:
print(tool["name"], tool["mutability"], tool["risk"])
Preview without execution:
preview = api.reasoning.execute_tool(
"dcc.execute",
{"host": "maya", "operation": "create_locator"},
dry_run=True,
)
Mutating tools require approval:
result = api.reasoning.execute_tool(
"dcc.execute",
{"host": "maya", "operation": "create_locator"},
approved=True,
)
If approved is false, the API returns APIResult(ok=False) before calling the
bridge.
Action Graphs and Prompt Chains
Reasoning and deterministic planning are separate operations.
graph = api.plan_prompt("Find function create_rig_mapping()")
preview = api.execute_action_graph(graph, dry_run=True)
Execute only after review:
report = api.execute_action_graph(graph, approved=True)
For multiple steps:
result = api.execute_prompt_chain(
[
"Export selected Maya animation clips",
"Import those clips into Unreal",
"Report the imported package paths",
],
dry_run=True,
)
DCC Bridge Calls
Application-local packages such as unreal, maya.cmds, bpy, and
MotionBuilder's SDK should run inside their host process.
result = api.dcc.unreal.find_assets(
"BP_Player",
expected_class="Blueprint",
)
Custom indexed function:
result = api.dcc.maya.call(
"custom_tools.animation.export_clips",
kwargs={"output_directory": "C:/exports"},
)
If the required host bridge is unavailable, the call returns an error. The API does not pretend that the host-side action completed.
Module-Level Convenience Functions
from tech_connector.api import (
execute_runtime_tool,
list_runtime_tools,
prepare_reasoning_request,
reason,
reasoning_capabilities,
reasoning_snapshot,
run_reasoning,
run_reasoning_chain,
)
reason aliases run_reasoning.
Constructor arguments are accepted by these functions:
settingsproject_rootrequire_entitlementcommand_routerlicensing_contextcommercial_useapp_major_version
Operation-specific arguments remain separate:
result = run_reasoning(
"Inspect the active file",
project_root="C:/project",
context={"current_file_path": "C:/project/tool.py"},
)
For related requests, use run_reasoning_chain (or api.reasoning.run_chain).
It carries the prior result's file/asset/operation workspace into each next
request, keeps only the latest 12 transcript messages, and stops when a step
needs clarification or fails. The returned state can be passed back as
context to resume a later chain after supplying the missing detail.
result = run_reasoning_chain(
["Find the export function", "Explain that function", "List its callers"],
project_root="C:/project",
)
if result.ok:
for step in result.result["steps"]:
print(step["response"]["text"])
else:
print(result.result["stop_reason"])
Error Handling
Never treat a returned object as successful without checking ok.
result = api.reasoning.run("Do the requested work")
if not result.ok:
print("Error:", result.error)
else:
response = result.result["response"]
if response["action"] == "clarify":
print("Input required:", response["text"])
Common failures:
| Failure | Meaning |
|---|---|
| License/login error | Official API access is not currently unlocked |
Unknown API feature |
The feature ID is not registered |
| Undeclared operation | The feature does not expose that operation |
| Approval required | A mutating runtime tool was blocked before execution |
| Bridge unavailable | The requested DCC is not connected |
| Runtime preconditions failed | A validation contract rejected preparation |
passthrough action |
No specialized route produced a final answer |
Performance Guidance
- Construct one
TechConnectorHeadlessAPIand reuse it. - The reasoning kernel and feature registry are initialized lazily and cached.
- Use
snapshotfor lightweight inspection. - Use
prepareonly when code-understanding context is needed. - Use
features.list(category=...)instead of filtering a large manifest in every caller. - Keep progress callbacks fast and non-blocking.
- Pass narrow project roots when the task is scoped.
- Use
dry_run=Truebefore mutating tools or action graphs.
Migration from API Version 1
Existing calls continue to work:
api.plan_prompt(...)
api.execute_action_graph(...)
api.execute_prompt_chain(...)
api.call_function(...)
api.call_dcc_function(...)
api.dcc.maya.create_rig(...)
API version 2 adds:
api.reasoning
api.runtime
api.features
No API version 1 method was removed or renamed.