Use Case

Secure AI Agent for Devices

Turn any device into an AI-powered agent, securely. Prompts flow in through Contact, get scanned by Surface for injection attacks, processed by Claude with conversation memory and MCP tools, scanned again for data leaks, and sent back to the device. Full loop, zero trust.

Coming soon Surface scanning docs

The problem with device-to-AI communication

Prompt injection from the edge

Devices in the field can be compromised. Untrusted prompts sent directly to an LLM can extract system prompts, leak credentials, or hijack model behavior.

No response sanitization

AI models can hallucinate API keys, internal URLs, or credentials from training data. Without scanning, sensitive data leaks straight to the device.

Stateless conversations

Each device request starts fresh. The AI has no memory of prior interactions, so it can't maintain context about device state, history, or ongoing diagnostics.

AI can't look things up

The model answers from its training data alone. It can't check device specs, query maintenance logs, or look up threshold configurations mid-conversation.

How Tendrl solves it

Three products, one closed loop. Every prompt is validated, scanned, processed with context and tools, scanned again, and delivered automatically.

1

Device sends a prompt via Contact

Your device publishes a message with tags: ["ai-agent"] containing the prompt and any context fields. Contact validates at ingress using DynamicActions: RequiredFields checks for prompt and device_id, type rules ensure correct formats. Messages always store; failed validation injects error tags and triggers an error workflow that sends field-level details back to the device.

MicroPython SDK: send a diagnostic prompt
client.publish(
    data={
        "prompt": "Diagnose high vibration on motor 3",
        "device_id": "motor-ctrl-07",
        "context": {"rpm": 3450, "temp_c": 78.2}
    },
    tags=["ai-agent"]
)
2

Surface scans the inbound prompt

The Strand workflow's first node is a Surface connector (surface.platform) using the Agentic scan profile. It checks for prompt injection, code extraction attempts, and sensitive data exfiltration, in 4–10 ms. The scan returns threat_level, score, and recommended_action directly into the workflow payload.

3

If/else branches on threat level

An if/else node checks threat_level. If the prompt is clean (score above 80), it continues to Claude. If flagged as malicious, a separate branch sends a rejection message back to the device via Contact's connector.contact_platform with the threat details, so the device can log the failure and retry with a safe prompt.

4

Claude processes with memory + MCP tools

This is where all three AI node capabilities come together:

Context (context_md) A system prompt defines the AI's role as a device diagnostic assistant, output format requirements, and safety constraints.
Templated prompt (Jinja2) The user prompt injects live device data (device_id, sensor readings, and the prompt text) from the Contact payload.
Conversation memory Redis-backed, keyed per node, with TTL of 7200 s and max 50 messages. The AI remembers prior interactions with this device: yesterday's diagnostic informs today's analysis.
MCP tool use An MCP server connector gives the AI access to a device database. Mid-conversation, it can look up device specs, maintenance history, threshold configs, or firmware versions.
Prompt template: device diagnostic
Device: {{  payload.device_id  }}
Current readings: RPM={{  payload.context.rpm  }}, Temp={{  payload.context.temp_c  }}°C

{{  payload.prompt  }}
5

Surface scans the response, Contact delivers

Before the response reaches the device, a second Surface node scans Claude's output for credential leaks, internal URLs, and PII using the sensitive data detection engine. If clean, a Contact connector sends the AI response back to the device entity with tag ai-response, and a second Contact node with operation update_state patches the device's state table with the last_ai_interaction timestamp.

MicroPython SDK: receive AI response
@client.on(tag="ai-response")
def handle_ai_reply(msg):
    print(msg.get("data", {}).get("response"))

Full-loop security, built in

Dual Surface scanning

Inbound prompts scanned for injection, outbound responses scanned for data leaks. Both under 10 ms for text payloads.

Conversation memory

Redis-backed per-node memory with configurable TTL and max messages. Devices get contextual AI, not stateless responses.

MCP tool use

Attach MCP servers so the AI can query databases, look up device specs, or check configs mid-conversation.

Passive validation

Contact validation is passive: messages always store. Failed tags trigger error workflows that notify the device with field-level details.

Zero-config Surface

The Surface connector in Strand uses an internal token. No API key to manage, no extra setup.

Loop prevention

strandTriggerDepth max 3 prevents Contact → Strand → Contact cycles from running away.

Example: motor diagnostic agent

Device prompt to AI response in one automated loop.

Device Sends prompt
Contact Validate + route
Surface Scan prompt
Claude + MCP Process + memory
Surface → Contact Scan + deliver
Ingest

Device publishes via MicroPython SDK with tags ["ai-agent"]. Contact validates RequiredFields (prompt, device_id) and type rules. Pass triggers the Strand workflow; fail triggers an error workflow that sends field-level errors back to the device.

Process

Surface scans the prompt for injection attacks (Agentic profile). If clean, Claude processes with 2-hour conversation memory and an MCP server for device lookups. The model can reference yesterday's diagnostic and pull live specs from the database.

Deliver

Surface scans Claude's response for credential and PII leaks. Contact sends the clean response back to the device entity and patches the state table with the last_ai_interaction timestamp.

Give your devices an AI brain, securely

Free tier includes 5 entities, 10 workflows, 550 runs/month, and 100 Surface scans. No credit card required.

Coming soon Surface docs