diff --git a/references/integrations.md b/references/integrations.md
index 71b3169..9484b14 100644
--- a/references/integrations.md
+++ b/references/integrations.md
@@ -13,7 +13,7 @@ Temporal ships and supports a growing set of integrations with third-party frame
| Integration | Language(s) | What it does | Reference | Related |
|---|---|---|---|---|
-| Spring Boot (`temporal-spring-boot-starter`) | Java | Auto-configuration of `WorkflowClient`, worker factories, workflow/activity bean registration, lifecycle, testing | `references/java/integrations/spring-boot.md` | `references/java/java.md` |
+| Spring Boot (`temporal-spring-boot-starter`) | Java | Auto-configuration of `WorkflowClient`, Worker factories, Workflow / Activity / Nexus Service bean auto-discovery, explicit `workers:` configuration (`task-queue`, `workflow-classes`, `activity-beans`), interceptor ordering via Spring `@Order`, options customization, testing | `references/java/integrations/spring-boot.md` | `references/java/java.md` |
| Spring AI (`temporal-spring-ai`) | Java | Durable Spring AI agents: chat-model calls run as Activities; tools dispatched per type (Activity stub, Nexus stub, `@SideEffectTool`, plain); vector stores, embeddings, and MCP clients auto-registered | `references/java/integrations/spring-ai.md` | `references/java/integrations/spring-boot.md`, `references/core/ai-patterns.md` |
| OpenAI Agents SDK (`temporalio.contrib.openai_agents`) | Python | Durable OpenAI Agents SDK agents: model calls run as Activities via `OpenAIAgentsPlugin`; tools are Activities (`activity_as_tool`) or workflow-resident `@function_tool`s; stateless/stateful MCP, sandbox backends, streaming, and OpenTelemetry export are supported | `references/python/integrations/openai-agents-sdk.md` | `references/python/ai-patterns.md`, `references/core/ai-patterns.md` |
| LangSmith tracing (`temporalio.contrib.langsmith`) | Python | Experimental Temporal Plugin that propagates LangSmith trace context across Worker boundaries; lets `@traceable` run inside Workflows and Activities | `references/python/integrations/langsmith.md` | `references/python/ai-patterns.md`, `references/core/ai-patterns.md` |
diff --git a/references/java/integrations/spring-boot.md b/references/java/integrations/spring-boot.md
index ceaaaec..df47b1a 100644
--- a/references/java/integrations/spring-boot.md
+++ b/references/java/integrations/spring-boot.md
@@ -2,60 +2,77 @@
## Overview
-`temporal-spring-boot-starter` auto-configures workers, registers workflow/activity implementations, and exposes `WorkflowClient` as a Spring bean. This eliminates the manual `WorkflowServiceStubs` → `WorkflowClient` → `WorkerFactory` setup required without Spring.
+`io.temporal:temporal-spring-boot-starter` auto-configures Workers, registers Workflow / Activity / Nexus Service implementations, and exposes `WorkflowClient` as a Spring bean. This eliminates the manual `WorkflowServiceStubs` to `WorkflowClient` to `WorkerFactory` setup required without Spring.
+
+Temporal's Spring Boot integration supports Spring Boot 2.x, 3.x, and 4.x .
## Dependency Setup
-Maven:
+Maven :
```xml
io.temporal
temporal-spring-boot-starter
- [1.0,)
+ 1.31.0
```
-Gradle:
+Gradle :
```groovy
-implementation 'io.temporal:temporal-spring-boot-starter:1.+'
+implementation 'io.temporal:temporal-spring-boot-starter:1.31.0'
```
-The starter transitively includes `temporal-sdk` and the autoconfigure module. You can declare both `temporal-sdk` and `temporal-spring-boot-starter` explicitly, but the starter alone is sufficient.
+The starter transitively includes `temporal-sdk` and the autoconfigure module.
## Minimal Configuration
-`application.properties`:
-```properties
-spring.temporal.connection.target=local
-spring.temporal.start-workers=true
-spring.temporal.workersAutoDiscovery.packages=greetingapp
+The minimum to autowire a `WorkflowClient` is a `connection.target` :
+
+```yaml
+spring.temporal:
+ connection:
+ target: local # shorthand for localhost:7233; use host:port for remote
```
-`application.yml` equivalent:
+To set a non-default Namespace, add `spring.temporal.namespace` :
+
```yaml
-spring:
- temporal:
- connection:
- target: local # shorthand for localhost:7233
- start-workers: true
- workersAutoDiscovery:
- packages:
- - greetingapp
- workers:
- - task-queue: greeting-queue
- name: greeting-worker
+spring.temporal:
+ connection:
+ target: local
+ namespace: my-namespace
```
-For self-hosted Temporal, replace `local` with the server address:
-```properties
-spring.temporal.connection.target=temporal.internal:7233
+### Temporal Cloud with API key
+
+```yaml
+spring.temporal:
+ connection:
+ target: ..tmprl.cloud:7233
+ apiKey:
+ namespace:
```
-## Interface Design + Spring Annotation Layering
+### Temporal Cloud with mTLS
+
+```yaml
+spring.temporal:
+ connection:
+ mtls:
+ target: ..tmprl.cloud:7233
+ key-file: /path/to/key.key
+ cert-chain-file: /path/to/cert.pem
+ namespace:
+```
-The key concept: Temporal SDK annotations go on **interfaces**, Spring Boot autoconfigure annotations go on **implementation classes**. This is identical to non-Spring usage at the interface level.
+`cert-chain-file` may be omitted when the `key-file` is a PKCS12 bundle that already contains the certificate chain .
+
+## Interface Design and Spring Annotation Layering
+
+Temporal SDK annotations go on **interfaces**, Spring Boot autoconfigure annotations go on **implementation classes**. The interface side is identical to non-Spring usage.
+
+### Workflow interface
-### Workflow Interface (unchanged from non-Spring)
```java
package greetingapp;
@@ -69,7 +86,10 @@ public interface GreetingWorkflow {
}
```
-### Workflow Implementation
+### Workflow implementation
+
+`io.temporal.spring.boot.WorkflowImpl` replaces the manual `worker.registerWorkflowImplementationTypes()` call. The `workers` member names the Worker(s) this class registers with.
+
```java
package greetingapp;
@@ -79,12 +99,10 @@ import io.temporal.workflow.Workflow;
import java.time.Duration;
-// @WorkflowImpl replaces manual worker.registerWorkflowImplementationTypes()
-// No @Component — workflows are NOT Spring beans; Temporal creates a new instance per execution
-@WorkflowImpl(taskQueues = "greeting-queue")
+// No @Component — Temporal creates a new instance per execution.
+@WorkflowImpl(workers = "greeting-worker")
public class GreetingWorkflowImpl implements GreetingWorkflow {
- // Activity stubs created via Workflow.newActivityStub() as usual
private final GreetActivities activities = Workflow.newActivityStub(
GreetActivities.class,
ActivityOptions.newBuilder()
@@ -100,7 +118,8 @@ public class GreetingWorkflowImpl implements GreetingWorkflow {
}
```
-### Activity Interface (unchanged from non-Spring)
+### Activity interface
+
```java
package greetingapp;
@@ -114,22 +133,22 @@ public interface GreetActivities {
}
```
-### Activity Implementation
+### Activity implementation
+
+`io.temporal.spring.boot.ActivityImpl` must be applied to a Spring bean; the documented way is to add `@Component` .
+
```java
package greetingapp;
import io.temporal.spring.boot.ActivityImpl;
import org.springframework.stereotype.Component;
-// @Component makes this a Spring bean — dependencies can be injected normally
-// @ActivityImpl replaces manual worker.registerActivitiesImplementations()
@Component
-@ActivityImpl(taskQueues = "greeting-queue")
+@ActivityImpl(workers = "greeting-worker") // docs/develop/java/integrations/spring-boot.mdx:157
public class GreetActivitiesImpl implements GreetActivities {
private final GreetingService greetingService;
- // Constructor injection works because this is a Spring bean
public GreetActivitiesImpl(GreetingService greetingService) {
this.greetingService = greetingService;
}
@@ -141,59 +160,92 @@ public class GreetActivitiesImpl implements GreetActivities {
}
```
-## Auto-Discovery
+Nexus Service implementations follow the same pattern using `io.temporal.spring.boot.NexusServiceImpl` ; the impl must be a Spring bean.
-Auto-discovery is how the autoconfigure finds and registers implementations without explicit configuration. It requires **both** of the following:
+## Configure Workers
-1. `@WorkflowImpl(taskQueues = "...")` or `@ActivityImpl(taskQueues = "...")` on the implementation class
-2. `spring.temporal.workersAutoDiscovery.packages` pointing to a package that contains those classes
+The integration supports two configuration methods for Workers: explicit configuration and auto-discovery . They compose: auto-discovery is applied **after and on top of** explicit configuration .
-Missing either one results in silent non-registration — no error, nothing polls the task queue.
+### Explicit configuration
-The `taskQueues` attribute routes implementations to the right worker when multiple task queues exist. A worker configured with task queue `"greeting-queue"` only picks up implementations annotated with `taskQueues = "greeting-queue"`.
+The `workers:` block lists Workers and their members :
-**Important:** `@ActivityImpl(taskQueues = "greeting-queue")` only registers the activity bean with that worker. It does not route individual activity task executions. Inside the workflow, `ActivityOptions.setTaskQueue("greeting-queue")` must also be set on the activity stub to route activity tasks to the correct queue.
+```yaml
+spring.temporal:
+ workers:
+ - task-queue: greeting-queue
+ name: greeting-worker # if omitted, the Task Queue name is used as the Worker name
+ workflow-classes:
+ - greetingapp.GreetingWorkflowImpl
+ activity-beans:
+ - greetActivitiesImpl
+```
+
+- `task-queue` is the Task Queue the Worker polls.
+- `name` is the unique Worker name; it defaults to the Task Queue when omitted .
+- `workflow-classes` lists fully qualified Workflow implementation class names .
+- `activity-beans` lists Spring bean names of Activity implementations .
+
+### Auto-discovery
+
+Auto-discovery lets you skip listing Workflow classes, Activity beans, and Nexus Service beans by referencing Worker Task Queue names or Worker names on the implementations themselves .
+
+```yaml
+spring.temporal:
+ workers-auto-discovery:
+ packages:
+ - greetingapp # docs/develop/java/integrations/spring-boot.mdx:138-142
+```
-### Comparison: Auto-Discovery vs Explicit YAML Registration
+#### Auto-discovery scope
+
+Auto-discovery picks up exactly the following :
+
+- Workflow implementation classes annotated with `io.temporal.spring.boot.WorkflowImpl` .
+- Activity beans present in the Spring context whose implementations are annotated with `io.temporal.spring.boot.ActivityImpl` .
+- Nexus Service beans present in the Spring context whose implementations are annotated with `io.temporal.spring.boot.NexusServiceImpl` .
+- Workers themselves — if a Task Queue or Worker name is referenced by one of the annotations but not explicitly configured, a Worker is created with default options .
+
+Auto-discovered Workflow classes, Activity beans, and Nexus Service beans are registered with configured Workers if not already registered .
+
+`ActivityImpl` and `NexusServiceImpl` only work when the implementation is a Spring bean (for example, annotated with `@Component`) .
+
+### Explicit vs auto-discovery, side by side
Auto-discovery via annotations:
-```properties
-spring.temporal.workersAutoDiscovery.packages=greetingapp
+
+```yaml
+spring.temporal:
+ workers-auto-discovery:
+ packages:
+ - greetingapp
```
```java
@Component
-@ActivityImpl(taskQueues = "greeting-queue")
-public class GreetActivitiesImpl implements GreetActivities { ... }
+@ActivityImpl(workers = "greeting-worker")
+public class GreetActivitiesImpl implements GreetActivities { }
```
-Explicit YAML registration (alternative):
+Explicit registration:
+
```yaml
-spring:
- temporal:
- workers:
- - task-queue: greeting-queue
- name: greeting-worker
- activity-beans:
- - greetActivitiesImpl
- workflow-classes:
- - greetingapp.GreetingWorkflowImpl
+spring.temporal:
+ workers:
+ - task-queue: greeting-queue
+ name: greeting-worker
+ workflow-classes:
+ - greetingapp.GreetingWorkflowImpl
+ activity-beans:
+ - greetActivitiesImpl
```
-Use auto-discovery when implementations are colocated in a single package tree (most apps). Use explicit YAML when you need fine-grained control, want to exclude specific classes, or are registering beans defined elsewhere.
+Use auto-discovery when implementations are colocated in a package tree (most apps). Use explicit configuration when registering beans defined outside scanned packages, or when you want the YAML to be the single source of truth.
## WorkflowClient Injection
-`WorkflowClient` is automatically registered as a Spring bean by the autoconfigure. Inject it into any `@Service` or `@RestController`:
+`WorkflowClient` is autowired by the integration . Inject it into any `@Service` or `@RestController`:
```java
-package greetingapp;
-
-import io.temporal.client.WorkflowClient;
-import io.temporal.client.WorkflowOptions;
-import org.springframework.stereotype.Service;
-
-import java.util.UUID;
-
@Service
public class GreetingStarter {
@@ -208,80 +260,93 @@ public class GreetingStarter {
GreetingWorkflow.class,
WorkflowOptions.newBuilder()
.setWorkflowId(UUID.randomUUID().toString())
- .setTaskQueue("greeting-queue") // must match the worker's task queue
+ .setTaskQueue("greeting-queue") // must match the Worker's Task Queue
.build()
);
- // Synchronous — blocks until workflow completes
return stub.greet(name);
}
-
- public void startGreetingAsync(String name) {
- var stub = client.newWorkflowStub(
- GreetingWorkflow.class,
- WorkflowOptions.newBuilder()
- .setWorkflowId(UUID.randomUUID().toString())
- .setTaskQueue("greeting-queue")
- .build()
- );
- // Fire-and-forget — returns immediately
- WorkflowClient.start(stub::greet, name);
- }
}
```
-## Worker Lifecycle
+## Interceptors
+
+Create beans implementing one of `io.temporal.common.interceptors.WorkflowClientInterceptor`, `io.temporal.common.interceptors.ScheduleClientInterceptor`, or `io.temporal.common.interceptors.WorkerInterceptor` . Registration order is controlled by Spring's `org.springframework.core.annotation.Order` annotation on each bean — lower values run first.
-Workers start on `ApplicationReadyEvent` — after the full Spring context is initialized (DB migrations run, all beans wired). This means activity beans are fully ready before any workflow tasks are processed.
+```java
+import io.temporal.common.interceptors.WorkerInterceptor;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
-To run a client-only app (one that submits workflows but does not execute them):
-```properties
-spring.temporal.start-workers=false
+@Component
+@Order(10)
+public class TracingWorkerInterceptor implements WorkerInterceptor {
+ // ...
+}
```
-## Testing Strategies
+These three interceptor interfaces are the only ordering hook the integration documents — there is no Temporal-specific ordering API. For broader extension (registering Workflow / Activity / Nexus types, modifying Worker or Client options across the SDK), see the [Temporal Plugin system](https://docs.temporal.io/develop/plugins-guide).
-See `references/java/testing.md` for full details on both approaches.
+## Customization of Options
-**Spring integration tests** — uses an embedded Temporal test server wired into the Spring context:
-```properties
-# src/test/resources/application-test.properties
-spring.temporal.test-server.enabled=true
-```
-```java
-@SpringBootTest
-@ActiveProfiles("test")
-class GreetingIntegrationTest {
- @Autowired WorkflowClient client; // points at the embedded test server
+Create a bean implementing `io.temporal.spring.boot.TemporalOptionsCustomizer` to programmatically adjust options after the YAML/property values are applied. The supported builder types are :
- @Test
- void testWorkflowThroughSpringContext() { ... }
-}
+- `WorkflowServiceStubsOptions.Builder`
+- `WorkflowClientOptions.Builder`
+- `WorkerFactoryOptions.Builder`
+- `WorkerOptions.Builder`
+- `WorkflowImplementationOptions.Builder`
+- `TestEnvironmentOptions.Builder`
+
+For per-Task-Queue or per-Worker-name customization of `WorkerOptions`, use `io.temporal.spring.boot.WorkerOptionsCustomizer` instead of the generic form . For per-Workflow-Type customization of `WorkflowImplementationOptions`, use `io.temporal.spring.boot.WorkflowImplementationOptionsCustomizer` .
+
+## Integrations (metrics and tracing)
+
+The integration picks up a `io.micrometer.core.instrument.MeterRegistry` bean (for example, from Spring Boot Actuator) and reports Temporal metrics through it .
+
+For tracing, the integration picks up the OpenTelemetry bean configured by `spring-cloud-sleuth-otel-autoconfigure`, or a custom `io.opentelemetry.api.OpenTelemetry` / `io.opentracing.Tracer` bean in the application context .
+
+The Spring AI integration (`io.temporal:temporal-spring-ai`) builds on this Spring Boot integration: when on the classpath, its `SpringAiPlugin` auto-registers `ChatModelActivity` with all Temporal Workers created by the Spring Boot integration .
+
+## Testing
+
+Switch the client to an in-memory `io.temporal.testing.TestWorkflowEnvironment` by enabling the test server :
+
+```yaml
+spring.temporal:
+ test-server:
+ enabled: true
```
-**Unit tests without Spring** — use `TestWorkflowEnvironment` or `TestWorkflowExtension` directly. No Spring context, faster startup, full time-skipping support:
+When `spring.temporal.test-server.enabled: true` is set, the `spring.temporal.connection` block is ignored . You can then autowire the `TestWorkflowEnvironment` alongside `WorkflowClient`:
+
```java
-@RegisterExtension
-static final TestWorkflowExtension testWorkflow = TestWorkflowExtension.newBuilder()
- .setWorkflowTypes(GreetingWorkflowImpl.class)
- .setDoNotStart(true)
- .build();
+@SpringBootTest(classes = Test.Configuration.class)
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+public class Test {
+ @Autowired ConfigurableApplicationContext applicationContext;
+ @Autowired TestWorkflowEnvironment testWorkflowEnvironment;
+ @Autowired WorkflowClient workflowClient;
+
+ @BeforeEach
+ void setUp() {
+ applicationContext.start();
+ }
+
+ @ComponentScan // discovers @Component-annotated Activity beans
+ public static class Configuration {}
+}
```
-Do not mix approaches in the same test class — choose one or the other.
+For unit tests without Spring, use `TestWorkflowExtension` or `TestWorkflowEnvironment` directly; see [Java SDK test frameworks](https://docs.temporal.io/develop/java/best-practices/testing-suite#test-frameworks). Don't mix Spring integration tests and direct `TestWorkflowExtension` tests in the same test class — pick one.
## Spring-Specific Gotchas
-**Workflow impls must not have `@Component`**
-Temporal creates a new workflow instance per execution via `beanFactory.createBean()` (not `getBean()`). Adding `@Component` means Spring also registers it as a singleton bean, which can cause confusing lifecycle behavior. Leave `@WorkflowImpl` classes as plain classes with no Spring annotations.
+**Workflow impls must not have `@Component`.** Temporal creates a new Workflow instance per execution. Adding `@Component` makes Spring also manage it as a singleton bean, causing confusing lifecycle behavior. Leave `@WorkflowImpl` classes as plain classes with no Spring stereotype.
-**Activity beans are Spring singletons**
-Temporal may invoke activity methods concurrently across many workflow executions. Keep activity implementations stateless — no mutable instance fields. Use injected services (which are themselves stateless or thread-safe) for all state.
+**Activity beans are Spring singletons.** Temporal may invoke Activity methods concurrently across many Workflow executions. Don't keep mutable instance state on Activity beans — use injected stateless or thread-safe services instead.
-**`@WorkflowImpl` / `@ActivityImpl` without `workersAutoDiscovery.packages` → silently ignored**
-This is the most common setup mistake. If auto-discovery packages are not configured, the annotations are never scanned and nothing registers with the worker. Verify with the Temporal UI that the worker is registering the expected workflow/activity types.
+**`@WorkflowImpl` / `@ActivityImpl` without `workers-auto-discovery.packages` is silently ignored.** Without the packages list, nothing scans the annotations and nothing registers. Verify in the Temporal UI that the Worker reports the expected Workflow and Activity types.
-**`ActivityOptions.setTaskQueue(...)` is required on activity stubs**
-`@ActivityImpl(taskQueues = "greeting-queue")` registers the activity bean with the worker — it does not set the default task queue for activity execution. Inside workflow code, always set `.setTaskQueue(...)` in `ActivityOptions` to explicitly route activity tasks to the correct worker.
+**`ActivityOptions.setTaskQueue(...)` is still required on Activity stubs.** `@ActivityImpl(workers = "...")` only binds the Activity bean to a Worker; it doesn't route Activity Task execution. Inside Workflow code, set `.setTaskQueue(...)` on `ActivityOptions` to direct Activity Tasks to the right queue.
-**Multiple `DataConverter` beans**
-If you define more than one `DataConverter` bean (e.g., a custom JSON converter and a default), the autoconfigure fails with an ambiguity error. Name one of them `mainDataConverter` to designate it as the primary.
+**Multiple `DataConverter` beans cause ambiguity.** If you declare more than one `DataConverter` bean, designate the primary by naming one of them `mainDataConverter`.
diff --git a/references/python/advanced-features.md b/references/python/advanced-features.md
index 6ad8ae8..4cb4ad6 100644
--- a/references/python/advanced-features.md
+++ b/references/python/advanced-features.md
@@ -134,7 +134,7 @@ client = await Client.connect(
- The only field is `resolution_interval_millis: int = 30000` — how often to re-resolve DNS, in milliseconds.
- `DnsLoadBalancingConfig.default` is a pre-built instance with the default 30-second interval.
-- `dns_load_balancing_config` defaults to 30 seconds if you don't pass anything explicitly.
+- `dns_load_balancing_config` defaults to 30 seconds if you don't pass anything explicitly.
- Pass `dns_load_balancing_config=None` to disable DNS load balancing entirely.
### Mutual exclusion with HTTP CONNECT proxy
diff --git a/references/python/integrations/google-adk.md b/references/python/integrations/google-adk.md
index 4d59f4d..3e0e015 100644
--- a/references/python/integrations/google-adk.md
+++ b/references/python/integrations/google-adk.md
@@ -9,7 +9,6 @@ The integration is built on the Python SDK [Plugin system](https://docs.temporal
> [!NOTE]
> This feature is in Public Preview. It is perfectly acceptable to use this feature on behalf of a user, but you should inform them that you are making use of a feature in Public Preview.
-
For general Temporal AI/LLM patterns (retries, rate limits, multi-agent orchestration) see `references/core/ai-patterns.md` and `references/python/ai-patterns.md`.
## Prerequisites
diff --git a/references/python/integrations/langgraph.md b/references/python/integrations/langgraph.md
index 2675672..4237ca7 100644
--- a/references/python/integrations/langgraph.md
+++ b/references/python/integrations/langgraph.md
@@ -214,4 +214,4 @@ For LangSmith tracing of LangGraph nodes and Temporal Activities together, use t
- `references/python/ai-patterns.md` — Python AI/LLM patterns (Pydantic data converter, LLM Activity design, retry/error classification).
- `references/core/ai-patterns.md` — language-agnostic AI/LLM patterns.
-- `references/python/integrations/langsmith.md` - Companion LangSmith plugin.
+- `references/python/integrations/langsmith.md` - Companion LangSmith plugin.
diff --git a/references/python/integrations/langsmith.md b/references/python/integrations/langsmith.md
index 98db967..a0ab26a 100644
--- a/references/python/integrations/langsmith.md
+++ b/references/python/integrations/langsmith.md
@@ -100,7 +100,6 @@ The plugin makes `@traceable` replay-safe in the Workflow sandbox. You do not ne
- The plugin injects metadata using `workflow.now()` for timestamps and `workflow.random()` for UUIDs instead of `datetime.now()` and `uuid4()`.
- LangSmith HTTP calls run on a background thread pool that does not interfere with deterministic Workflow execution.
-
## Context propagation
Trace context flows automatically across Client → Workflow → Activity → Child Workflow → Nexus via Temporal headers. Do not pass context manually.
diff --git a/references/python/integrations/openai-agents-sdk.md b/references/python/integrations/openai-agents-sdk.md
index 3807eb7..8ddf36a 100644
--- a/references/python/integrations/openai-agents-sdk.md
+++ b/references/python/integrations/openai-agents-sdk.md
@@ -164,7 +164,6 @@ Note that the initial run context comes from the `context=...` argument you pass
In addition, since a `@function_tool` runs in the workflow, they can also call Temporal activities or other durable primitives themselves.
-
**Don't put I/O, system clock, or sources of randomness inside a `@function_tool` body.** Make it an `@activity.defn` and wrap with `activity_as_tool` instead.
### Picking between the two
diff --git a/references/python/workflow-streams.md b/references/python/workflow-streams.md
index 84ecbd7..b53915b 100644
--- a/references/python/workflow-streams.md
+++ b/references/python/workflow-streams.md
@@ -11,7 +11,6 @@ Use it for modest fan-out progress streaming: AI-agent runs, order pipelines, mu
Only available in the Python SDK today; cross-language is on the roadmap.
-
## When to use / not to use
- Use it for: updating a UI as an AI agent works; surfacing status from a payment or order pipeline; reporting intermediate results from a data job.
diff --git a/references/ruby/gotchas.md b/references/ruby/gotchas.md
index c2e962c..e56391d 100644
--- a/references/ruby/gotchas.md
+++ b/references/ruby/gotchas.md
@@ -59,7 +59,6 @@ require_relative 'activities/my_activity'
Transient network errors should be retried. Authentication errors should not be. See `references/ruby/error-handling.md` to understand how to classify errors with `non_retryable: true` and `non_retryable_error_types`.
-
## Heartbeating
### Forgetting to Heartbeat Long Activities