callback_url is currently derived from LISTEN_ADDR, which is the local bind address of the HTTP server, not a public URL that OpenClaw can call back to.
Evidence
internal/ai_client/client.go:68 builds the callback as http://<LISTEN_ADDR>/callback
internal/config/config.go:72-74 defaults LISTEN_ADDR to :8080
cmd/bridge/main.go:68-69 also uses LISTEN_ADDR as the server bind address
requirements.md:81-86 requires dispatch payload to include callback_url
Why this is a problem
With the default config, the generated callback URL becomes http://:8080/callback, which is not a usable external URL.
In common deployments the service binds to :8080 or 0.0.0.0:8080, but OpenClaw needs a public hostname/URL to reach the callback.
Reusing the same variable for both bind address and advertised callback URL makes reverse-proxy or tunnel deployments impossible without code changes.
Expected behavior
Keep LISTEN_ADDR only for local server binding.
Add a separate config value for the public callback base URL and use that when generating callback_url.
Impact
End-to-end dispatch can succeed while the callback never reaches the bridge in real deployments.
## Summary
`callback_url` is currently derived from `LISTEN_ADDR`, which is the local bind address of the HTTP server, not a public URL that OpenClaw can call back to.
## Evidence
- `internal/ai_client/client.go:68` builds the callback as `http://<LISTEN_ADDR>/callback`
- `internal/config/config.go:72-74` defaults `LISTEN_ADDR` to `:8080`
- `cmd/bridge/main.go:68-69` also uses `LISTEN_ADDR` as the server bind address
- `requirements.md:81-86` requires dispatch payload to include `callback_url`
## Why this is a problem
- With the default config, the generated callback URL becomes `http://:8080/callback`, which is not a usable external URL.
- In common deployments the service binds to `:8080` or `0.0.0.0:8080`, but OpenClaw needs a public hostname/URL to reach the callback.
- Reusing the same variable for both bind address and advertised callback URL makes reverse-proxy or tunnel deployments impossible without code changes.
## Expected behavior
- Keep `LISTEN_ADDR` only for local server binding.
- Add a separate config value for the public callback base URL and use that when generating `callback_url`.
## Impact
End-to-end dispatch can succeed while the callback never reaches the bridge in real deployments.
Agreed direction: separate bind address from callback URL generation.
Scope
Keep LISTEN_ADDR for HTTP bind only.
Add CALLBACK_BASE_URL for dispatch payload callback URL.
If CALLBACK_BASE_URL is unset, default to http://localhost.
Steps
Config update + tests
Add CallbackBaseURL to config.
Read from env CALLBACK_BASE_URL.
Default to http://localhost when empty.
Add unit tests in internal/config/config_test.go.
Dispatcher update + tests
Replace callback generation from LISTEN_ADDR with callback base URL.
Add helper to normalize trailing slash and append /callback.
Add unit tests in internal/ai_client/client_test.go.
Docs/env update
Update .env.example and README:
LISTEN_ADDR = local bind only.
CALLBACK_BASE_URL = public callback base, localhost fallback.
Verification
go test ./internal/config -run CallbackBaseURL -v
go test ./internal/ai_client -run BuildCallbackURL -v
go test ./...
Tracking
Full detailed execution plan is saved at: docs/superpowers/plans/2026-04-27-callback-base-url.md
## Implementation plan
Agreed direction: separate bind address from callback URL generation.
### Scope
- Keep `LISTEN_ADDR` for HTTP bind only.
- Add `CALLBACK_BASE_URL` for dispatch payload callback URL.
- If `CALLBACK_BASE_URL` is unset, default to `http://localhost`.
### Steps
1. **Config update + tests**
- Add `CallbackBaseURL` to config.
- Read from env `CALLBACK_BASE_URL`.
- Default to `http://localhost` when empty.
- Add unit tests in `internal/config/config_test.go`.
2. **Dispatcher update + tests**
- Replace callback generation from `LISTEN_ADDR` with callback base URL.
- Add helper to normalize trailing slash and append `/callback`.
- Add unit tests in `internal/ai_client/client_test.go`.
3. **Docs/env update**
- Update `.env.example` and README:
- `LISTEN_ADDR` = local bind only.
- `CALLBACK_BASE_URL` = public callback base, localhost fallback.
4. **Verification**
- `go test ./internal/config -run CallbackBaseURL -v`
- `go test ./internal/ai_client -run BuildCallbackURL -v`
- `go test ./...`
### Tracking
- Full detailed execution plan is saved at:
`docs/superpowers/plans/2026-04-27-callback-base-url.md`
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
callback_urlis currently derived fromLISTEN_ADDR, which is the local bind address of the HTTP server, not a public URL that OpenClaw can call back to.Evidence
internal/ai_client/client.go:68builds the callback ashttp://<LISTEN_ADDR>/callbackinternal/config/config.go:72-74defaultsLISTEN_ADDRto:8080cmd/bridge/main.go:68-69also usesLISTEN_ADDRas the server bind addressrequirements.md:81-86requires dispatch payload to includecallback_urlWhy this is a problem
http://:8080/callback, which is not a usable external URL.:8080or0.0.0.0:8080, but OpenClaw needs a public hostname/URL to reach the callback.Expected behavior
LISTEN_ADDRonly for local server binding.callback_url.Impact
End-to-end dispatch can succeed while the callback never reaches the bridge in real deployments.
Implementation plan
Agreed direction: separate bind address from callback URL generation.
Scope
LISTEN_ADDRfor HTTP bind only.CALLBACK_BASE_URLfor dispatch payload callback URL.CALLBACK_BASE_URLis unset, default tohttp://localhost.Steps
Config update + tests
CallbackBaseURLto config.CALLBACK_BASE_URL.http://localhostwhen empty.internal/config/config_test.go.Dispatcher update + tests
LISTEN_ADDRwith callback base URL./callback.internal/ai_client/client_test.go.Docs/env update
.env.exampleand README:LISTEN_ADDR= local bind only.CALLBACK_BASE_URL= public callback base, localhost fallback.Verification
go test ./internal/config -run CallbackBaseURL -vgo test ./internal/ai_client -run BuildCallbackURL -vgo test ./...Tracking
docs/superpowers/plans/2026-04-27-callback-base-url.mdclosed by #6