Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
LAYERCODE_API_KEY=
LAYERCODE_WEBHOOK_SECRET=

# Optional LayerCode agent ID (for --unsafe-update-webhook)
LAYERCODE_AGENT_ID=

# Optional observability
LOGFIRE_TOKEN=

Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file.

- Full support for all LayerCode webhook event types: `session.start`, `message`, `data`, `session.update`, `session.end`
- New `outdoor_shop` agent: A customer service agent for the fictional "Nimbus Gear" outdoor equipment store with more complex tool responses (to mimic `stream.data` payloads)
- Auto-update webhook URL via `--unsafe-update-webhook` flag when using `--tunnel` (requires `LAYERCODE_AGENT_ID`)


## [0.0.1] - 2025-11-02
Expand Down
28 changes: 26 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ uvx layercode-create-app run --tunnel
```

This command will:
1. Scaffold and start a FastAPI server with the default agent
1. Start a FastAPI server with the default agent
2. Launch a Cloudflare tunnel and display your public webhook URL
3. Show you exactly where to paste the URL in your LayerCode dashboard
3. Show you exactly where to paste the URL in your LayerCode dashboard (if you didn't use `--unsafe-update-webhook`)

> **Tip:** Add `--unsafe-update-webhook` to skip manual webhook setting in Layercode dashboard (see [Auto-Update Webhook](#auto-update-webhook-quick-testing)).

### Example Output

Expand Down Expand Up @@ -120,6 +122,8 @@ uvx layercode-create-app run --agent bakery --tunnel
| `--agent-route` | `/api/agent` | Webhook route path |
| `--authorize-route` | `/api/authorize` | Authorization route path |
| `--tunnel` | `False` | Launch a Cloudflare quick tunnel for public access |
| `--agent-id` | env `LAYERCODE_AGENT_ID` | Agent ID for webhook auto-update |
| `--unsafe-update-webhook` | `False` | Auto-update agent webhook URL to tunnel URL (requires `--tunnel`) |
| `--env-file` | `.env` | Path to environment file to load before running |
| `--verbose`, `-v` | `False` | Enable DEBUG logging for detailed request traces |

Expand Down Expand Up @@ -162,6 +166,26 @@ When you use the `--tunnel` flag:

This makes it trivial to develop and test voice agents without deploying to production infrastructure.

### Auto-Update Webhook (Quick Testing)

For rapid iteration, use `--unsafe-update-webhook` to automatically update your LayerCode agent's webhook URL to the tunnel URL:

```bash
# Set your agent ID in .env
LAYERCODE_AGENT_ID=agent_...

# Run with auto-update
uvx layercode-create-app run --tunnel --unsafe-update-webhook
```

This will:
1. Start the tunnel and get a public URL
2. Fetch the current webhook URL from your agent (and save it)
3. Update your agent's webhook to the new tunnel URL
4. On shutdown, restore the previous webhook URL

> **WARNING: This flag modifies your LayerCode agent's webhook configuration via the API. Do NOT use this with production agents—it will disrupt live traffic. Only use with dedicated development/test agents.**

---

## Logging & Observability
Expand Down
8 changes: 8 additions & 0 deletions docs/api/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ uv run layercode-create-app run [OPTIONS]
| `--agent-route` | string | `/api/agent` | Webhook endpoint path |
| `--authorize-route` | string | `/api/authorize` | Authorization endpoint path |
| `--tunnel` | flag | `False` | Launch Cloudflare tunnel |
| `--agent-id` | string | from env | Agent ID for webhook auto-update |
| `--unsafe-update-webhook` | flag | `False` | Auto-update agent webhook to tunnel URL |
| `--env-file` | path | `.env` | Environment file to load |
| `--verbose`, `-v` | flag | `False` | Enable debug logging |

Expand All @@ -48,6 +50,11 @@ Use a specific AI model:
uv run layercode-create-app run --agent starter --model openai:gpt-4
```

Auto-update webhook URL for quick testing:
```bash
uv run layercode-create-app run --tunnel --unsafe-update-webhook --agent-id agent_xxx
```

### `list-agents`

List all available agents (built-in and custom).
Expand Down Expand Up @@ -91,6 +98,7 @@ OPENAI_API_KEY=sk-... # or GOOGLE_GENERATIVEAI_API_KEY
```env
DEFAULT_MODEL=openai:gpt-5-nano
LOGFIRE_TOKEN=lf_...
LAYERCODE_AGENT_ID=agent_... # For --unsafe-update-webhook
```

## Exit Codes
Expand Down
18 changes: 16 additions & 2 deletions docs/getting-started/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ DEFAULT_MODEL=openai:gpt-5-nano
# Logfire token for observability
LOGFIRE_TOKEN=lf_...

# Agent-specific configuration
AGENT_ID=agent_...
# LayerCode agent ID (for --unsafe-update-webhook)
LAYERCODE_AGENT_ID=agent_...
```

## CLI Configuration
Expand All @@ -53,6 +53,8 @@ Configure the `run` command:
--agent-route PATH # Webhook route (default: /api/agent)
--authorize-route PATH # Auth route (default: /api/authorize)
--tunnel # Enable Cloudflare tunnel
--agent-id ID # Agent ID for webhook auto-update
--unsafe-update-webhook # Auto-update webhook to tunnel URL
```

## Model Configuration
Expand Down Expand Up @@ -120,6 +122,18 @@ uv run layercode-create-app run --tunnel

The tunnel URL will be printed to the console. Copy the full webhook URL to your LayerCode dashboard.

### Auto-Update Webhook

For quick testing, automatically update your LayerCode agent's webhook URL:

```bash
uv run layercode-create-app run --tunnel --unsafe-update-webhook
```

This requires `LAYERCODE_AGENT_ID` in your `.env` (or `--agent-id` flag). On shutdown, the previous webhook URL is automatically restored.

> **WARNING:** Do NOT use `--unsafe-update-webhook` with production agents—it will disrupt live traffic.

### Tunnel Logs

Enable verbose logging to see tunnel activity:
Expand Down
35 changes: 35 additions & 0 deletions src/layercode_create_app/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ def run(
tunnel: bool,
verbose: bool,
env_file: str,
agent_id: str | None,
unsafe_update_webhook: bool,
) -> None:
"""Start the FastAPI server with optional Cloudflare tunnel."""

Expand All @@ -57,6 +59,9 @@ def run(
"authorize_route": authorize_route,
}

if agent_id:
overrides["layercode_agent_id"] = agent_id

settings = base_settings.model_copy(update=overrides)

if not settings.layercode_api_key:
Expand All @@ -67,6 +72,18 @@ def run(
print("Error: Missing LAYERCODE_WEBHOOK_SECRET in environment or overrides.")
sys.exit(1)

# Validate unsafe_update_webhook requirements
if unsafe_update_webhook:
if not tunnel:
print("Error: --unsafe-update-webhook requires --tunnel flag")
sys.exit(1)
if not settings.layercode_agent_id:
print(
"Error: --unsafe-update-webhook requires LAYERCODE_AGENT_ID "
"env var or --agent-id argument"
)
sys.exit(1)

chosen_model = model if model else settings.default_model

try:
Expand Down Expand Up @@ -98,6 +115,9 @@ async def serve() -> None:
settings.port,
settings.agent_route,
settings.cloudflare_bin,
settings.layercode_agent_id,
settings.layercode_api_key,
unsafe_update_webhook,
)

async def run_server() -> None:
Expand Down Expand Up @@ -172,6 +192,19 @@ def main() -> None:
action="store_true",
help="Launch a Cloudflare tunnel alongside the server",
)
run_parser.add_argument(
"--agent-id",
default=None,
help="Agent ID for webhook updates (overrides LAYERCODE_AGENT_ID env var)",
)
run_parser.add_argument(
"--unsafe-update-webhook",
action="store_true",
help=(
"Automatically update agent webhook URL when using --tunnel "
"(requires --agent-id or LAYERCODE_AGENT_ID)"
),
)
run_parser.add_argument(
"--verbose",
"-v",
Expand Down Expand Up @@ -199,6 +232,8 @@ def main() -> None:
tunnel=args.tunnel,
verbose=args.verbose,
env_file=args.env_file,
agent_id=args.agent_id,
unsafe_update_webhook=args.unsafe_update_webhook,
)
else:
parser.print_help()
Expand Down
1 change: 1 addition & 0 deletions src/layercode_create_app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class AppSettings(BaseSettings):

layercode_api_key: str | None = None
layercode_webhook_secret: str | None = None
layercode_agent_id: str | None = None

logfire_token: str | None = None

Expand Down
Loading
Loading