About intents
- Explanation
- 7-min read
Intents are the platform mechanism for context-aware cross-app navigation. When a user interacts with a resource—such as an entity, a metric, or a DQL query—and wants to do something with it in another app, an intent carries the relevant context from the source app to the target app through the AppShell.
Every Dynatrace app runs inside an iframe hosted by the AppShell. Regular links can navigate between apps, but they can't carry structured context with them. Intents solve this: they let your app pass data—entity IDs, timeframes, queries—to another app in a way the platform can coordinate, so the target app knows what to show.
How to deliver an intent
Intents reach users through different mechanisms, ordered by specificity. Choosing the right one determines whether users land where they need to go or get stuck picking from a list.
Explicit intents
Use an explicit intent when your app knows exactly where to send the user. The user clicks, the target app opens with all context applied. No dialog, no choices.

This is the most common pattern. It powers primary actions in intent menus and the left side of the IntentButton split button, the primary action such as View in Hosts or Open in Notebooks.
-
When to use—the target app and action are obvious for the resource type. You're connecting a host entity to the Hosts app, a trace ID to Distributed Traces, a DQL query to Notebooks. The 80/20 case.
-
How it works—your app calls
sendIntent()with arecommendedAppIdandrecommendedIntentId, or uses the<IntentButton>with those options set. The AppShell skips the Open with... dialog and opens the target app directly.
<IntentButton
payload={{ 'dt.entity.host': 'HOST-F66B242CD3A5E38E' }}
options={{
recommendedAppId: 'dynatrace.classic.hosts',
recommendedIntentId: 'view-host',
}}
>
View in Hosts
</IntentButton>
Do not hardcode your own entity-to-app mappings. Use the platform's recommended intents mapping to determine which target app and intent ID to use for a given resource type. This keeps navigation consistent across the platform.
Open with... dialog (fallback)
The Open with... dialog is the fallback that surfaces every app capable of handling the current intent payload. It appears when no explicit intent is configured or when the user deliberately wants to see all options.
-
When it appears:
- Your app calls
sendIntent()without specifying arecommendedAppId. - The user clicks the three-dot menu on an
IntentButtonand selects the Open with... option. - The
recommendedAppIddoesn't exist or can't handle the payload.
- Your app calls
-
What to know:
- Always provide this as a fallback. Do not suppress it.
- In the
IntentButtonsplit button, the Open with... option sits at the bottom of the three-dot menu, after explicit intents and add-ons. - The label must be exactly
Open with...with no variations.
The IntentButton
The IntentButton is a split button from the Strato Design System that implements all three mechanisms in one component. The left side triggers the primary explicit intent directly, for example, View in Hosts. The right side opens a menu with additional explicit intents, add-ons, and Open with... as the last option.

Use IntentButton for straightforward cases. Use sendIntent() from @dynatrace-sdk/navigation when you need more control over the trigger. For example, responding to a table row click or a custom interaction.
Recommended intents
Without central coordination, each app builds its own mapping from resource types to target apps. This creates inconsistency: clicking a host ID in one app opens the Hosts app, while clicking the same ID in another opens something different.
Recommended intents solve this with a centrally managed mapping from resource types to recommended target apps. Instead of hardcoding recommendedAppId: 'dynatrace.classic.hosts' in your source code, you query the recommended intents list to get the right target for dt.entity.host.
This ensures users always land in the same destination for the same resource type, regardless of which app they started from.
How intents work under the hood
Lifecycle
-
Source app sends an intent—your app calls
sendIntent(payload, options)or renders an<IntentButton>. The communication uses thewindow.postMessageAPI to reach the AppShell. -
AppShell resolves the target—if a
recommendedAppIdandrecommendedIntentIdare provided and valid, the AppShell opens that app directly. Otherwise, it finds all installed apps whose intent declarations match the payload properties and shows the "Open with..." dialog. -
AppShell launches the target app—the target app opens in an iframe (full page for navigation intents, modal for add-ons). The intent payload is passed as URL query arguments.
-
Target app handles the intent—the target app calls
getIntent()to read the payload and perform the requested action.
Intent matching
The AppShell matches an intent payload against every installed app's intent declarations in app.config.json. A match occurs when an app declares intent properties that the source app's payload satisfies:
- If the target declares
dt.entity.hostasrequired: true, the source must includedt.entity.hostin the payload. - Extra properties in the payload that the target does not declare are stripped before delivery.
- Use
keyPropertiesinsendIntent()to narrow matching when your payload contains multiple properties.
Payload structure
An intent payload is a set of key-value pairs carrying the context to share:
import { IntentPayload } from '@dynatrace-sdk/navigation';
const intent: IntentPayload = {
'dt.entity.host': 'HOST-F66B242CD3A5E38E',
'dt.timeframe': { from: 'now-2h', to: 'now' },
};
Common payload properties include entity IDs (dt.entity.*), DQL queries (dt.query), and timeframes (dt.timeframe). The target app defines which properties it accepts and requires in its intent declaration.
Limitations
- One-way payload delivery—the initial intent payload is passed via URL query arguments when the target app loads. For two-way communication, use intents-with-response, where the target add-on can pass data back asynchronously.
- Keep payloads concise—while the previous URL length limitation has been fixed, it's still best practice to pass identifiers and queries rather than large data blobs.
Security context
Every Dynatrace app runs inside its own cross-origin iframe in the AppShell. API calls from any app, whether it opened via a regular intent or as a modal add-on, run under that app's security context, not the calling app's. Each app uses its own identity, OAuth scopes, and permissions.
Cross-origin iFrames comply with the AppShell's Content Security Policy rules.
Context sharing
When a target app opens through an intent, it can access:
- Platform context shared between all apps: timeframe, segment, tenant info
- Intent payload—the specific data passed by the source app via the intent
- The target app does not have access to the source app's internal state beyond what is in the intent payload.
This applies equally to full-page navigation intents and modal add-ons.
Intents as public APIs
Intents behave like public APIs. An app's intent types define its public contract. Consuming apps can rely on a specific intent type always accepting the same payload shape.
- Intent types have owners, just like API owners own API types.
- The intent type name and its required properties form a stable interface.
- Breaking changes to an intent's required properties are breaking API changes and require a deprecation process to phase out safely.
Choose the right mechanism
| Scenario | Use | Why |
|---|---|---|
| User clicks a host entity and should open in the relevant app | Recommended intent | Resolve the target app dynamically, do not hardcode the destination |
| App needs to support a resource type it cannot predict upfront | Open with... | Let the platform's matching find the right targets |
Intent naming guidelines
Every intent has two user-facing identifiers, which affect discoverability and clarity:
- The intent ID—which is the key in
app.config - The description—shown on hover in the intent menu
Intent IDs
The intent ID is the key you declare in your app configuration under app.intents. It should be short, lowercase, and describe the action your app performs.
Use kebab-case for new intent IDs:
| Do | Don't |
|---|---|
view-host | ViewHost |
share-chart | shareChart |
create-alert | alert |
view-host-v2 | view_host_deprecated |
Some older intents use snake_case as in view_host or view_service. Both formats work, but kebab-case is the preferred convention for new intents.
Follow these rules:
- Use lowercase letters, underscores, and hyphens only. No spaces, no camelCase.
- Start with a verb that describes the action. For example,
view,create,edit,share,add, oranalyze. - Don't include the app name. The intent ID should describe the action, not the destination. The platform maps actions to apps.
- Don't include
deprecated,new, oroldin the intent ID. Use a-v2suffix for versioned replacements. - Keep it short. The ID appears in URLs and API calls.
Descriptions
The description field is a short sentence that appears as the label in the intent context menu and in the Open with... dialog. It tells the user what will happen.
Follow this format: [action verb] + [object]. See the following table:
| Good | Bad | Why |
|---|---|---|
| "View the host" | "Host" | Names the destination, not the action |
| "Add to dashboard" | "Dashboard" | Names the destination, not the action |
| "Analyze query results" | "Notebooks" | Users choose by action, not app name |
| "Create alert" | "Alerting" | Gerund or category name, not an action |
The description should complete the sentence This will.... If This will Host doesn't make sense, rewrite it.
Next steps
- Send intents—define payloads and trigger intents from your app
- Receive intents—declare intent types and handle incoming payloads
- Debug intents—troubleshoot intent matching and delivery