diff --git a/frontend/src/app/components/agent-status-badge/agent-status-badge.component.html b/frontend/src/app/components/agent-status-badge/agent-status-badge.component.html
new file mode 100644
index 0000000..e88ea86
--- /dev/null
+++ b/frontend/src/app/components/agent-status-badge/agent-status-badge.component.html
@@ -0,0 +1,8 @@
+
+
+ {{ displayLabel }}
+
\ No newline at end of file
diff --git a/frontend/src/app/components/agent-status-badge/agent-status-badge.component.scss b/frontend/src/app/components/agent-status-badge/agent-status-badge.component.scss
new file mode 100644
index 0000000..331d6f9
--- /dev/null
+++ b/frontend/src/app/components/agent-status-badge/agent-status-badge.component.scss
@@ -0,0 +1,146 @@
+// ============================================================================
+// Agent Status Badge — per spec Section 7.3
+// Colored pill with dot indicator and optional pulse animation.
+// ============================================================================
+
+$badge-height: 24px;
+$dot-size: 8px;
+$border-radius: 12px;
+$font-size: 12px;
+$font-weight: 500;
+$padding-x: 8px;
+$gap: 6px;
+
+@use 'sass:color';
+
+// Status color palette
+$color-active: #22c55e; // green-500
+$color-idle: #9ca3af; // gray-400
+$color-thinking: #3b82f6; // blue-500
+$color-error: #ef4444; // red-500
+$color-offline: #9ca3af; // gray-400
+
+// Background tints (12% opacity for soft pill background)
+$bg-active: rgba($color-active, 0.12);
+$bg-idle: rgba($color-idle, 0.12);
+$bg-thinking: rgba($color-thinking, 0.12);
+$bg-error: rgba($color-error, 0.12);
+$bg-offline: rgba($color-offline, 0.12);
+
+// ---------------------------------------------------------------------------
+// Base pill
+// ---------------------------------------------------------------------------
+.badge {
+ display: inline-flex;
+ align-items: center;
+ height: $badge-height;
+ padding: 0 $padding-x;
+ border-radius: $border-radius;
+ gap: $gap;
+ font-size: $font-size;
+ font-weight: $font-weight;
+ line-height: 1;
+ white-space: nowrap;
+ user-select: none;
+}
+
+// ---------------------------------------------------------------------------
+// Dot indicator
+// ---------------------------------------------------------------------------
+.badge__dot {
+ width: $dot-size;
+ height: $dot-size;
+ border-radius: 50%;
+ flex-shrink: 0;
+}
+
+// ---------------------------------------------------------------------------
+// Label text
+// ---------------------------------------------------------------------------
+.badge__label {
+ line-height: 1;
+}
+
+// ---------------------------------------------------------------------------
+// Status color variants
+// ---------------------------------------------------------------------------
+.badge--active {
+ background: $bg-active;
+ color: color.adjust($color-active, $lightness: -10%);
+
+ .badge__dot {
+ background: $color-active;
+ }
+}
+
+.badge--idle {
+ background: $bg-idle;
+ color: color.adjust($color-idle, $lightness: -15%);
+
+ .badge__dot {
+ background: $color-idle;
+ }
+}
+
+.badge--thinking {
+ background: $bg-thinking;
+ color: color.adjust($color-thinking, $lightness: -10%);
+
+ .badge__dot {
+ background: $color-thinking;
+ }
+}
+
+.badge--error {
+ background: $bg-error;
+ color: color.adjust($color-error, $lightness: -10%);
+
+ .badge__dot {
+ background: $color-error;
+ }
+}
+
+.badge--offline {
+ background: $bg-offline;
+ color: color.adjust($color-offline, $lightness: -15%);
+
+ .badge__dot {
+ background: $color-offline;
+ }
+}
+
+// ---------------------------------------------------------------------------
+// Pulse animation — applied when status is active, thinking, or error
+// ---------------------------------------------------------------------------
+.badge--pulse {
+ .badge__dot {
+ animation: pulse-dot 2s ease-in-out infinite;
+ }
+}
+
+// Active: 2s pulse
+.badge--active.badge--pulse .badge__dot {
+ animation-duration: 2s;
+}
+
+// Thinking: 3s pulse
+.badge--thinking.badge--pulse .badge__dot {
+ animation-duration: 3s;
+}
+
+// Error: 0.8s pulse (fast, urgent)
+.badge--error.badge--pulse .badge__dot {
+ animation-duration: 0.8s;
+}
+
+@keyframes pulse-dot {
+ 0%,
+ 100% {
+ opacity: 1;
+ transform: scale(1);
+ }
+ 50% {
+ opacity: 0.4;
+ transform: scale(1.5);
+ }
+}
\ No newline at end of file
diff --git a/frontend/src/app/components/agent-status-badge/agent-status-badge.component.ts b/frontend/src/app/components/agent-status-badge/agent-status-badge.component.ts
new file mode 100644
index 0000000..a246d63
--- /dev/null
+++ b/frontend/src/app/components/agent-status-badge/agent-status-badge.component.ts
@@ -0,0 +1,54 @@
+import { ChangeDetectionStrategy, Component, input } from '@angular/core';
+import { AgentStatus } from '../../models/agent.model';
+
+/**
+ * Agent Status Badge component.
+ * Displays a colored pill with a pulse animation indicating the agent's current status.
+ * Per spec Section 7.3: Agent Card Component Interface — status indicator.
+ *
+ * Color mapping:
+ * - Active → green
+ * - Idle → gray
+ * - Thinking → blue
+ * - Error → red
+ * - Offline → gray (no pulse)
+ *
+ * Pulse animations:
+ * - Active → 2s
+ * - Error → 0.8s
+ * - Thinking → 3s
+ * - Idle / Offline → no pulse
+ */
+@Component({
+ selector: 'app-agent-status-badge',
+ standalone: true,
+ imports: [],
+ templateUrl: './agent-status-badge.component.html',
+ styleUrl: './agent-status-badge.component.scss',
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class AgentStatusBadgeComponent {
+ /** Current agent status — binds to the AgentStatus type from the model. */
+ readonly status = input.required();
+
+ /** Label text shown inside the badge. Defaults to title-cased status. */
+ readonly label = input();
+
+ get displayLabel(): string {
+ return this.label() ?? this.titleCase(this.status());
+ }
+
+ /** CSS class driven by the current status value. */
+ get statusClass(): string {
+ return `badge--${this.status()}`;
+ }
+
+ /** Whether the pulse animation should be active for the current status. */
+ get hasPulse(): boolean {
+ return this.status() === 'active' || this.status() === 'thinking' || this.status() === 'error';
+ }
+
+ private titleCase(value: string): string {
+ return value.charAt(0).toUpperCase() + value.slice(1);
+ }
+}
\ No newline at end of file
diff --git a/frontend/src/app/components/agent-status-badge/index.ts b/frontend/src/app/components/agent-status-badge/index.ts
new file mode 100644
index 0000000..e531d31
--- /dev/null
+++ b/frontend/src/app/components/agent-status-badge/index.ts
@@ -0,0 +1 @@
+export { AgentStatusBadgeComponent } from './agent-status-badge.component';
\ No newline at end of file
diff --git a/frontend/src/app/components/index.ts b/frontend/src/app/components/index.ts
new file mode 100644
index 0000000..09c8fb9
--- /dev/null
+++ b/frontend/src/app/components/index.ts
@@ -0,0 +1 @@
+export { AgentStatusBadgeComponent } from './agent-status-badge/agent-status-badge.component';
\ No newline at end of file